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     */
017    package org.apache.logging.log4j.status;
018    
019    import java.io.IOException;
020    import java.io.PrintStream;
021    
022    import org.apache.logging.log4j.Level;
023    
024    /**
025     * StatusListener that writes to the Console.
026     */
027    @SuppressWarnings("UseOfSystemOutOrSystemErr")
028    public 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    }