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