001package org.slf4j.helpers;
002
003import java.io.PrintStream;
004
005/**
006 * An internally used class for reporting internal messages generated by SLF4J itself during initialization.
007 *
008 * <p>
009 * Internal reporting is performed by calling the {@link #info(String)}, {@link #warn(String)} (String)}
010 * {@link #error(String)} (String)}  and {@link  #error(String, Throwable)} methods.
011 * </p>
012 * <p>See {@link #SLF4J_INTERNAL_VERBOSITY_KEY} and {@link #SLF4J_INTERNAL_REPORT_STREAM_KEY} for
013 * configuration options.</p>
014 * <p>
015 * <p>
016 * Note that this system is independent of the logging back-end in use.
017 *
018 * @since 2.0.10
019 */
020public class Reporter {
021
022    /**
023     * this class is used internally by Reporter
024     */
025    private enum Level {
026        INFO(1), WARN(2), ERROR(3);
027
028        int levelInt;
029
030        private Level(int levelInt) {
031            this.levelInt = levelInt;
032        }
033
034        private int getLevelInt() {
035            return levelInt;
036        }
037    }
038
039    private enum TargetChoice {
040        Stderr, Stdout;
041    }
042
043    static final String SLF4J_INFO_PREFIX = "SLF4J(I): ";
044    static final String SLF4J_WARN_PREFIX = "SLF4J(W): ";
045    static final String SLF4J_ERROR_PREFIX = "SLF4J(E): ";
046
047
048    /**
049     * This system property controls the target for internal reports output by SLF4J.
050     * Recognized values for this key are "System.out", "stdout", "sysout", "System.err",
051     * "stderr" and "syserr".
052     *
053     * <p>By default, output is directed to "stderr".</p>
054     */
055    public static final String SLF4J_INTERNAL_REPORT_STREAM_KEY = "slf4j.internal.report.stream";
056    static private final String[] SYSOUT_KEYS = {"System.out", "stdout", "sysout"};
057
058    /**
059     * This system property controls the internal level of chattiness
060     * of SLF4J. Recognized settings are "INFO", "WARN" and "ERROR". The default value is "INFO".
061     */
062    public static final String SLF4J_INTERNAL_VERBOSITY_KEY = "slf4j.internal.verbosity";
063
064
065    static private final TargetChoice TARGET_CHOICE = initTargetChoice();
066
067    static private final Level INTERNAL_VERBOSITY = initVerbosity();
068
069    static private TargetChoice initTargetChoice() {
070        String reportStreamStr = System.getProperty(SLF4J_INTERNAL_REPORT_STREAM_KEY);
071
072        if(reportStreamStr == null || reportStreamStr.isEmpty()) {
073            return TargetChoice.Stderr;
074        }
075
076        for(String s : SYSOUT_KEYS) {
077            if(s.equalsIgnoreCase(reportStreamStr))
078                return TargetChoice.Stdout;
079        }
080        return TargetChoice.Stderr;
081    }
082
083
084    static private Level initVerbosity() {
085        String verbosityStr = System.getProperty(SLF4J_INTERNAL_VERBOSITY_KEY);
086
087        if(verbosityStr == null || verbosityStr.isEmpty()) {
088            return Level.INFO;
089        }
090
091        if(verbosityStr.equalsIgnoreCase("ERROR")) {
092            return Level.ERROR;
093        }
094
095
096        if(verbosityStr.equalsIgnoreCase("WARN")) {
097            return Level.WARN;
098        }
099
100        return Level.INFO;
101    }
102
103    static boolean isEnabledFor(Level level) {
104        return (level.levelInt >= INTERNAL_VERBOSITY.levelInt);
105    }
106
107    static private PrintStream getTarget() {
108        switch(TARGET_CHOICE) {
109            case Stdout:
110                return System.out;
111            case Stderr:
112            default:
113                return System.err;
114        }
115    }
116
117    /**
118     * Report an internal message of level INFO. Message text is prefixed with the string "SLF4J(I)", with
119     * (I) standing as a shorthand for INFO.
120     *
121     * <p>Messages of level INFO are be enabled when the {@link #SLF4J_INTERNAL_VERBOSITY_KEY} system property is
122     * set to "INFO" and disabled when set to "WARN" or "ERROR". By default, {@link #SLF4J_INTERNAL_VERBOSITY_KEY} is
123     * set to "INFO".</p>
124     *
125     * @param msg the message text
126     */
127    public static void info(String msg) {
128        if(isEnabledFor(Level.INFO)) {
129            getTarget().println(SLF4J_INFO_PREFIX + msg);
130        }
131    }
132
133
134    /**
135     * Report an internal message of level "WARN". Message text is prefixed with the string "SLF4J(W)", with
136     * (W) standing as a shorthand for  WARN.
137     *
138     * <p>Messages of level WARN are be enabled when the {@link #SLF4J_INTERNAL_VERBOSITY_KEY} system property is
139     * set to "INFO" or "WARN" and disabled when set to "ERROR". By default, {@link #SLF4J_INTERNAL_VERBOSITY_KEY} is
140     * set to "INFO".</p>
141     *
142     * @param msg the message text
143     */
144    static final public void warn(String msg) {
145        if(isEnabledFor(Level.WARN)) {
146            getTarget().println(SLF4J_WARN_PREFIX + msg);
147        }
148    }
149
150
151    /**
152     * Report an internal message of level "ERROR  accompanied by a {@link Throwable}.
153     * Message text is prefixed with the string "SLF4J(E)", with (E) standing as a shorthand for ERROR.
154     *
155     * <p>Messages of level ERROR are always enabled.
156     *
157     * @param msg the message text
158     * @param t a Throwable
159     */
160    static final public void error(String msg, Throwable t) {
161        // error cannot be disabled
162        getTarget().println(SLF4J_ERROR_PREFIX + msg);
163        getTarget().println(SLF4J_ERROR_PREFIX + "Reported exception:");
164        t.printStackTrace(getTarget());
165    }
166
167
168    /**
169     * Report an internal message of level "ERROR". Message text is prefixed with the string "SLF4J(E)", with
170     * (E)  standing as a shorthand for ERROR.
171     *
172     * <p>Messages of level ERROR are always enabled.
173     *
174     * @param msg the message text
175     */
176
177    static final public void error(String msg) {
178        // error cannot be disabled
179        getTarget().println(SLF4J_ERROR_PREFIX + msg);
180    }
181}