001/*
002 * (C) Copyright 2011-2012 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Julien Carsique
018 *
019 */
020
021package org.nuxeo.log4j;
022
023import java.io.BufferedReader;
024import java.io.IOException;
025import java.io.InputStream;
026import java.io.InputStreamReader;
027import java.io.OutputStream;
028import java.util.List;
029import java.util.concurrent.atomic.AtomicInteger;
030
031import org.apache.commons.io.IOUtils;
032import org.apache.commons.logging.Log;
033import org.apache.commons.logging.LogFactory;
034import org.apache.commons.logging.impl.SimpleLog;
035
036/**
037 * Helper class for logging process output
038 *
039 * @since 5.4.1
040 */
041public class ThreadedStreamGobbler extends Thread {
042    static final Log log = LogFactory.getLog(ThreadedStreamGobbler.class);
043
044    private static final String DEFAULT_PREFIX = "Nuxeo-stream-gobbler-";
045
046    private static AtomicInteger threadNumber = new AtomicInteger();
047
048    private InputStream is;
049
050    private int logLevel;
051
052    private List<String> output;
053
054    private OutputStream outputStream;
055
056    public ThreadedStreamGobbler(String prefix, InputStream is, int logLevel) {
057        this.is = is;
058        this.logLevel = logLevel;
059        this.setDaemon(true);
060        setName(prefix + threadNumber.incrementAndGet());
061    }
062
063    public ThreadedStreamGobbler(InputStream is, int logLevel) {
064        this(DEFAULT_PREFIX, is, logLevel);
065    }
066
067    /**
068     * @param inputStream InputStream to read
069     * @param output List to store output instead of logging it.
070     * @since 5.5
071     */
072    public ThreadedStreamGobbler(InputStream inputStream, List<String> output) {
073        this(inputStream, SimpleLog.LOG_LEVEL_OFF);
074        this.output = output;
075    }
076
077    /**
078     * @param inputStream InputStream to read
079     * @param output OutputStream where to write.
080     * @since 5.5
081     */
082    public ThreadedStreamGobbler(InputStream inputStream, OutputStream output) {
083        this(inputStream, SimpleLog.LOG_LEVEL_OFF);
084        this.outputStream = output;
085    }
086
087    @Override
088    public void run() {
089        BufferedReader br = new BufferedReader(new InputStreamReader(is));
090        String line;
091        final byte[] newLine = "\n".getBytes();
092
093        try {
094            while ((line = br.readLine()) != null) {
095                switch (logLevel) {
096                case SimpleLog.LOG_LEVEL_DEBUG:
097                    log.debug(line);
098                    break;
099                case SimpleLog.LOG_LEVEL_INFO:
100                    log.info(line);
101                    break;
102                case SimpleLog.LOG_LEVEL_ERROR:
103                    log.error(line);
104                    break;
105                case SimpleLog.LOG_LEVEL_OFF:
106                    if (output != null) {
107                        output.add(line);
108                    }
109                    if (outputStream != null) {
110                        outputStream.write(line.getBytes());
111                        outputStream.write(newLine);
112                    }
113                default:
114                    break;
115                }
116            }
117        } catch (IOException e) {
118            log.error(e);
119        } finally {
120            IOUtils.closeQuietly(br);
121        }
122    }
123}