001package org.slf4j.simple;
002
003import java.io.FileNotFoundException;
004import java.io.FileOutputStream;
005import java.io.InputStream;
006import java.io.PrintStream;
007import java.security.AccessController;
008import java.security.PrivilegedAction;
009import java.text.DateFormat;
010import java.text.SimpleDateFormat;
011import java.util.Properties;
012
013import org.slf4j.helpers.Util;
014import org.slf4j.simple.OutputChoice.OutputChoiceType;
015
016/**
017 * This class holds configuration values for {@link SimpleLogger}. The
018 * values are computed at runtime. See {@link SimpleLogger} documentation for
019 * more information.
020 * 
021 * 
022 * @author Ceki Gülcü
023 * @author Scott Sanders
024 * @author Rod Waldhoff
025 * @author Robert Burrell Donkin
026 * @author Cédrik LIME
027 * 
028 * @since 1.7.25
029 */
030public class SimpleLoggerConfiguration {
031
032    private static final String CONFIGURATION_FILE = "simplelogger.properties";
033
034    static int DEFAULT_LOG_LEVEL_DEFAULT = SimpleLogger.LOG_LEVEL_INFO;
035    int defaultLogLevel = DEFAULT_LOG_LEVEL_DEFAULT;
036
037    private static final boolean SHOW_DATE_TIME_DEFAULT = false;
038    boolean showDateTime = SHOW_DATE_TIME_DEFAULT;
039
040    private static final String DATE_TIME_FORMAT_STR_DEFAULT = null;
041    private static String dateTimeFormatStr = DATE_TIME_FORMAT_STR_DEFAULT;
042
043    DateFormat dateFormatter = null;
044
045    private static final boolean SHOW_THREAD_NAME_DEFAULT = true;
046    boolean showThreadName = SHOW_THREAD_NAME_DEFAULT;
047
048    /**
049     * See https://jira.qos.ch/browse/SLF4J-499
050     * @since 1.7.33 and 2.0.0-alpha6
051     */
052    private static final boolean SHOW_THREAD_ID_DEFAULT = false;
053    boolean showThreadId = SHOW_THREAD_ID_DEFAULT;
054    
055    final static boolean SHOW_LOG_NAME_DEFAULT = true;
056    boolean showLogName = SHOW_LOG_NAME_DEFAULT;
057
058    private static final boolean SHOW_SHORT_LOG_NAME_DEFAULT = false;
059    boolean showShortLogName = SHOW_SHORT_LOG_NAME_DEFAULT;
060
061    private static final boolean LEVEL_IN_BRACKETS_DEFAULT = false;
062    boolean levelInBrackets = LEVEL_IN_BRACKETS_DEFAULT;
063
064    private static final String LOG_FILE_DEFAULT = "System.err";
065    private String logFile = LOG_FILE_DEFAULT;
066    OutputChoice outputChoice = null;
067
068    private static final boolean CACHE_OUTPUT_STREAM_DEFAULT = false;
069    private boolean cacheOutputStream = CACHE_OUTPUT_STREAM_DEFAULT;
070
071    private static final String WARN_LEVELS_STRING_DEFAULT = "WARN";
072    String warnLevelString = WARN_LEVELS_STRING_DEFAULT;
073
074    private final Properties properties = new Properties();
075
076    void init() {
077        loadProperties();
078
079        String defaultLogLevelString = getStringProperty(SimpleLogger.DEFAULT_LOG_LEVEL_KEY, null);
080        if (defaultLogLevelString != null)
081            defaultLogLevel = stringToLevel(defaultLogLevelString);
082
083        showLogName = getBooleanProperty(SimpleLogger.SHOW_LOG_NAME_KEY, SimpleLoggerConfiguration.SHOW_LOG_NAME_DEFAULT);
084        showShortLogName = getBooleanProperty(SimpleLogger.SHOW_SHORT_LOG_NAME_KEY, SHOW_SHORT_LOG_NAME_DEFAULT);
085        showDateTime = getBooleanProperty(SimpleLogger.SHOW_DATE_TIME_KEY, SHOW_DATE_TIME_DEFAULT);
086        showThreadName = getBooleanProperty(SimpleLogger.SHOW_THREAD_NAME_KEY, SHOW_THREAD_NAME_DEFAULT);
087        showThreadId = getBooleanProperty(SimpleLogger.SHOW_THREAD_ID_KEY, SHOW_THREAD_ID_DEFAULT);
088        dateTimeFormatStr = getStringProperty(SimpleLogger.DATE_TIME_FORMAT_KEY, DATE_TIME_FORMAT_STR_DEFAULT);
089        levelInBrackets = getBooleanProperty(SimpleLogger.LEVEL_IN_BRACKETS_KEY, LEVEL_IN_BRACKETS_DEFAULT);
090        warnLevelString = getStringProperty(SimpleLogger.WARN_LEVEL_STRING_KEY, WARN_LEVELS_STRING_DEFAULT);
091
092        logFile = getStringProperty(SimpleLogger.LOG_FILE_KEY, logFile);
093
094        cacheOutputStream = getBooleanProperty(SimpleLogger.CACHE_OUTPUT_STREAM_STRING_KEY, CACHE_OUTPUT_STREAM_DEFAULT);
095        outputChoice = computeOutputChoice(logFile, cacheOutputStream);
096
097        if (dateTimeFormatStr != null) {
098            try {
099                dateFormatter = new SimpleDateFormat(dateTimeFormatStr);
100            } catch (IllegalArgumentException e) {
101                Util.report("Bad date format in " + CONFIGURATION_FILE + "; will output relative time", e);
102            }
103        }
104    }
105
106    private void loadProperties() {
107        // Add props from the resource simplelogger.properties
108        InputStream in = AccessController.doPrivileged((PrivilegedAction<InputStream>) () -> {
109            ClassLoader threadCL = Thread.currentThread().getContextClassLoader();
110            if (threadCL != null) {
111                return threadCL.getResourceAsStream(CONFIGURATION_FILE);
112            } else {
113                return ClassLoader.getSystemResourceAsStream(CONFIGURATION_FILE);
114            }
115        });
116        if (null != in) {
117            try {
118                properties.load(in);
119            } catch (java.io.IOException e) {
120                // ignored
121            } finally {
122                try {
123                    in.close();
124                } catch (java.io.IOException e) {
125                    // ignored
126                }
127            }
128        }
129    }
130
131    String getStringProperty(String name, String defaultValue) {
132        String prop = getStringProperty(name);
133        return (prop == null) ? defaultValue : prop;
134    }
135
136    boolean getBooleanProperty(String name, boolean defaultValue) {
137        String prop = getStringProperty(name);
138        return (prop == null) ? defaultValue : "true".equalsIgnoreCase(prop);
139    }
140
141    String getStringProperty(String name) {
142        String prop = null;
143        try {
144            prop = System.getProperty(name);
145        } catch (SecurityException e) {
146            ; // Ignore
147        }
148        return (prop == null) ? properties.getProperty(name) : prop;
149    }
150
151    static int stringToLevel(String levelStr) {
152        if ("trace".equalsIgnoreCase(levelStr)) {
153            return SimpleLogger.LOG_LEVEL_TRACE;
154        } else if ("debug".equalsIgnoreCase(levelStr)) {
155            return SimpleLogger.LOG_LEVEL_DEBUG;
156        } else if ("info".equalsIgnoreCase(levelStr)) {
157            return SimpleLogger.LOG_LEVEL_INFO;
158        } else if ("warn".equalsIgnoreCase(levelStr)) {
159            return SimpleLogger.LOG_LEVEL_WARN;
160        } else if ("error".equalsIgnoreCase(levelStr)) {
161            return SimpleLogger.LOG_LEVEL_ERROR;
162        } else if ("off".equalsIgnoreCase(levelStr)) {
163            return SimpleLogger.LOG_LEVEL_OFF;
164        }
165        // assume INFO by default
166        return SimpleLogger.LOG_LEVEL_INFO;
167    }
168
169    private static OutputChoice computeOutputChoice(String logFile, boolean cacheOutputStream) {
170        if ("System.err".equalsIgnoreCase(logFile))
171            if (cacheOutputStream)
172                return new OutputChoice(OutputChoiceType.CACHED_SYS_ERR);
173            else
174                return new OutputChoice(OutputChoiceType.SYS_ERR);
175        else if ("System.out".equalsIgnoreCase(logFile)) {
176            if (cacheOutputStream)
177                return new OutputChoice(OutputChoiceType.CACHED_SYS_OUT);
178            else
179                return new OutputChoice(OutputChoiceType.SYS_OUT);
180        } else {
181            try {
182                FileOutputStream fos = new FileOutputStream(logFile);
183                PrintStream printStream = new PrintStream(fos);
184                return new OutputChoice(printStream);
185            } catch (FileNotFoundException e) {
186                Util.report("Could not open [" + logFile + "]. Defaulting to System.err", e);
187                return new OutputChoice(OutputChoiceType.SYS_ERR);
188            }
189        }
190    }
191
192}