001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017package org.apache.logging.log4j.status;
018
019import java.io.IOException;
020import java.io.PrintStream;
021
022import org.apache.logging.log4j.Level;
023
024/**
025 * StatusListener that writes to the Console.
026 */
027@SuppressWarnings("UseOfSystemOutOrSystemErr")
028public class StatusConsoleListener implements StatusListener {
029
030    private Level level = Level.FATAL;
031    private String[] filters;
032    private final PrintStream stream;
033
034    /**
035     * Creates the StatusConsoleListener using the supplied Level.
036     * @param level The Level of status messages that should appear on the console.
037     */
038    public StatusConsoleListener(final Level level) {
039        this(level, System.out);
040    }
041
042    /**
043     * Creates the StatusConsoleListener using the supplied Level. Make sure not to use a logger stream of some sort
044     * to avoid creating an infinite loop of indirection!
045     * @param level The Level of status messages that should appear on the console.
046     * @param stream The PrintStream to write to.
047     * @throws IllegalArgumentException if the PrintStream argument is {@code null}.
048     */
049    public StatusConsoleListener(final Level level, final PrintStream stream) {
050        if (stream == null) {
051            throw new IllegalArgumentException("You must provide a stream to use for this listener.");
052        }
053        this.level = level;
054        this.stream = stream;
055    }
056
057    /**
058     * Sets the level to a new value.
059     * @param level The new Level.
060     */
061    public void setLevel(final Level level) {
062        this.level = level;
063    }
064
065    /**
066     * Return the Log Level for which the Listener should receive events.
067     * @return the Log Level.
068     */
069    @Override
070    public Level getStatusLevel() {
071        return this.level;
072    }
073
074    /**
075     * Writes status messages to the console.
076     * @param data The StatusData.
077     */
078    @Override
079    public void log(final StatusData data) {
080        if (!filtered(data)) {
081            stream.println(data.getFormattedStatus());
082        }
083    }
084
085    /**
086     * Adds package name filters to exclude.
087     * @param filters An array of package names to exclude.
088     */
089    public void setFilters(final String... filters) {
090        this.filters = filters;
091    }
092
093    private boolean filtered(final StatusData data) {
094        if (filters == null) {
095            return false;
096        }
097        final String caller = data.getStackTraceElement().getClassName();
098        for (final String filter : filters) {
099            if (caller.startsWith(filter)) {
100                return true;
101            }
102        }
103        return false;
104    }
105
106    @Override
107    public void close() throws IOException {
108        // only want to close non-system streams
109        if (this.stream != System.out && this.stream != System.err) {
110            this.stream.close();
111        }
112    }
113}