View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.slf4j;
20  
21  import java.io.FileNotFoundException;
22  import java.io.FileOutputStream;
23  import java.io.InputStream;
24  import java.io.PrintStream;
25  import java.time.format.DateTimeFormatter;
26  import java.util.Properties;
27  
28  import org.apache.maven.api.Constants;
29  import org.apache.maven.slf4j.OutputChoice.OutputChoiceType;
30  import org.slf4j.helpers.Reporter;
31  
32  /**
33   * This class holds configuration values for {@link MavenBaseLogger}. The
34   * values are computed at runtime. See {@link MavenBaseLogger} documentation for
35   * more information.
36   *
37   *
38   * @author Ceki Gülcü
39   * @author Scott Sanders
40   * @author Rod Waldhoff
41   * @author Robert Burrell Donkin
42   * @author Cédrik LIME
43   *
44   * @since 1.7.25
45   */
46  public class SimpleLoggerConfiguration {
47  
48      private static final String CONFIGURATION_FILE = "maven.logger.properties";
49  
50      @Deprecated(since = "4.0.0")
51      private static final String LEGACY_CONFIGURATION_FILE = "simplelogger.properties";
52  
53      static final int DEFAULT_LOG_LEVEL_DEFAULT = MavenBaseLogger.LOG_LEVEL_INFO;
54      int defaultLogLevel = DEFAULT_LOG_LEVEL_DEFAULT;
55  
56      private static final boolean SHOW_DATE_TIME_DEFAULT = false;
57      boolean showDateTime = SHOW_DATE_TIME_DEFAULT;
58  
59      private static final String DATE_TIME_FORMAT_STR_DEFAULT = null;
60      DateTimeFormatter dateFormatter = null;
61  
62      private static final boolean SHOW_THREAD_NAME_DEFAULT = true;
63      boolean showThreadName = SHOW_THREAD_NAME_DEFAULT;
64  
65      /**
66       * See https://jira.qos.ch/browse/SLF4J-499
67       * @since 1.7.33 and 2.0.0-alpha6
68       */
69      private static final boolean SHOW_THREAD_ID_DEFAULT = false;
70  
71      boolean showThreadId = SHOW_THREAD_ID_DEFAULT;
72  
73      static final boolean SHOW_LOG_NAME_DEFAULT = true;
74      boolean showLogName = SHOW_LOG_NAME_DEFAULT;
75  
76      private static final boolean SHOW_SHORT_LOG_NAME_DEFAULT = false;
77      boolean showShortLogName = SHOW_SHORT_LOG_NAME_DEFAULT;
78  
79      private static final boolean LEVEL_IN_BRACKETS_DEFAULT = false;
80      boolean levelInBrackets = LEVEL_IN_BRACKETS_DEFAULT;
81  
82      private static final String LOG_FILE_DEFAULT = "System.err";
83      private String logFile = LOG_FILE_DEFAULT;
84      OutputChoice outputChoice = null;
85  
86      private static final boolean CACHE_OUTPUT_STREAM_DEFAULT = false;
87      private boolean cacheOutputStream = CACHE_OUTPUT_STREAM_DEFAULT;
88  
89      private static final String WARN_LEVELS_STRING_DEFAULT = "WARN";
90      String warnLevelString = WARN_LEVELS_STRING_DEFAULT;
91  
92      private final Properties properties = new Properties();
93  
94      void init() {
95          // Reset state before initialization
96          dateFormatter = null;
97  
98          loadProperties();
99  
100         String defaultLogLevelString = getStringProperty(Constants.MAVEN_LOGGER_DEFAULT_LOG_LEVEL, null);
101         if (defaultLogLevelString != null) {
102             defaultLogLevel = stringToLevel(defaultLogLevelString);
103         }
104 
105         // local variable,
106         String dateTimeFormatStr;
107 
108         showLogName = getBooleanProperty(Constants.MAVEN_LOGGER_SHOW_LOG_NAME, SHOW_LOG_NAME_DEFAULT);
109         showShortLogName = getBooleanProperty(Constants.MAVEN_LOGGER_SHOW_SHORT_LOG_NAME, SHOW_SHORT_LOG_NAME_DEFAULT);
110         showDateTime = getBooleanProperty(Constants.MAVEN_LOGGER_SHOW_DATE_TIME, SHOW_DATE_TIME_DEFAULT);
111         showThreadName = getBooleanProperty(Constants.MAVEN_LOGGER_SHOW_THREAD_NAME, SHOW_THREAD_NAME_DEFAULT);
112         showThreadId = getBooleanProperty(Constants.MAVEN_LOGGER_SHOW_THREAD_ID, SHOW_THREAD_ID_DEFAULT);
113         dateTimeFormatStr = getStringProperty(Constants.MAVEN_LOGGER_DATE_TIME_FORMAT, DATE_TIME_FORMAT_STR_DEFAULT);
114         levelInBrackets = getBooleanProperty(Constants.MAVEN_LOGGER_LEVEL_IN_BRACKETS, LEVEL_IN_BRACKETS_DEFAULT);
115         warnLevelString = getStringProperty(Constants.MAVEN_LOGGER_WARN_LEVEL, WARN_LEVELS_STRING_DEFAULT);
116 
117         logFile = getStringProperty(Constants.MAVEN_LOGGER_LOG_FILE, logFile);
118 
119         cacheOutputStream = getBooleanProperty(Constants.MAVEN_LOGGER_CACHE_OUTPUT_STREAM, CACHE_OUTPUT_STREAM_DEFAULT);
120         outputChoice = computeOutputChoice(logFile, cacheOutputStream);
121 
122         if (dateTimeFormatStr != null) {
123             try {
124                 dateFormatter = DateTimeFormatter.ofPattern(dateTimeFormatStr);
125             } catch (IllegalArgumentException e) {
126                 Reporter.error("Bad date format in " + CONFIGURATION_FILE + "; will output relative time", e);
127             }
128         }
129     }
130 
131     private void loadProperties() {
132         ClassLoader threadCL = Thread.currentThread().getContextClassLoader();
133         ClassLoader toUseCL = (threadCL != null ? threadCL : ClassLoader.getSystemClassLoader());
134 
135         // Try loading maven properties first
136         boolean mavenPropsLoaded = false;
137         try (InputStream in = toUseCL.getResourceAsStream(CONFIGURATION_FILE)) {
138             if (in != null) {
139                 properties.load(in);
140                 mavenPropsLoaded = true;
141             }
142         } catch (java.io.IOException e) {
143             // ignored
144         }
145 
146         // Try loading legacy properties
147         try (InputStream in = toUseCL.getResourceAsStream(LEGACY_CONFIGURATION_FILE)) {
148             if (in != null) {
149                 Properties legacyProps = new Properties();
150                 legacyProps.load(in);
151                 if (!mavenPropsLoaded) {
152                     Reporter.warn("Using deprecated " + LEGACY_CONFIGURATION_FILE + ". Please migrate to "
153                             + CONFIGURATION_FILE);
154                 }
155                 // Only load legacy properties if there's no maven equivalent
156                 for (String propName : legacyProps.stringPropertyNames()) {
157                     String mavenKey = propName.replace(MavenBaseLogger.LEGACY_PREFIX, Constants.MAVEN_LOGGER_PREFIX);
158                     if (!properties.containsKey(mavenKey)) {
159                         properties.setProperty(mavenKey, legacyProps.getProperty(propName));
160                     }
161                 }
162             }
163         } catch (java.io.IOException e) {
164             // ignored
165         }
166     }
167 
168     String getStringProperty(String name, String defaultValue) {
169         String prop = getStringProperty(name);
170         return (prop == null) ? defaultValue : prop;
171     }
172 
173     boolean getBooleanProperty(String name, boolean defaultValue) {
174         String prop = getStringProperty(name);
175         return (prop == null) ? defaultValue : "true".equalsIgnoreCase(prop);
176     }
177 
178     String getStringProperty(String name) {
179         String prop = null;
180         try {
181             // Try maven property first
182             prop = System.getProperty(name);
183             if (prop == null && name.startsWith(Constants.MAVEN_LOGGER_PREFIX)) {
184                 // Try legacy property
185                 String legacyName = name.replace(Constants.MAVEN_LOGGER_PREFIX, MavenBaseLogger.LEGACY_PREFIX);
186                 prop = System.getProperty(legacyName);
187                 if (prop != null) {
188                     Reporter.warn("Using deprecated property " + legacyName + ". Please migrate to " + name);
189                 }
190             }
191         } catch (SecurityException e) {
192             // Ignore
193         }
194 
195         if (prop == null) {
196             prop = properties.getProperty(name);
197             if (prop == null && name.startsWith(Constants.MAVEN_LOGGER_PREFIX)) {
198                 // Try legacy property from properties file
199                 String legacyName = name.replace(Constants.MAVEN_LOGGER_PREFIX, MavenBaseLogger.LEGACY_PREFIX);
200                 prop = properties.getProperty(legacyName);
201                 if (prop != null) {
202                     Reporter.warn("Using deprecated property " + legacyName + ". Please migrate to " + name);
203                 }
204             }
205         }
206         return prop;
207     }
208 
209     static int stringToLevel(String levelStr) {
210         if ("trace".equalsIgnoreCase(levelStr)) {
211             return MavenBaseLogger.LOG_LEVEL_TRACE;
212         } else if ("debug".equalsIgnoreCase(levelStr)) {
213             return MavenBaseLogger.LOG_LEVEL_DEBUG;
214         } else if ("info".equalsIgnoreCase(levelStr)) {
215             return MavenBaseLogger.LOG_LEVEL_INFO;
216         } else if ("warn".equalsIgnoreCase(levelStr)) {
217             return MavenBaseLogger.LOG_LEVEL_WARN;
218         } else if ("error".equalsIgnoreCase(levelStr)) {
219             return MavenBaseLogger.LOG_LEVEL_ERROR;
220         } else if ("off".equalsIgnoreCase(levelStr)) {
221             return MavenBaseLogger.LOG_LEVEL_OFF;
222         }
223         // assume INFO by default
224         return MavenBaseLogger.LOG_LEVEL_INFO;
225     }
226 
227     private static OutputChoice computeOutputChoice(String logFile, boolean cacheOutputStream) {
228         if ("System.err".equalsIgnoreCase(logFile)) {
229             return new OutputChoice(cacheOutputStream ? OutputChoiceType.CACHED_SYS_ERR : OutputChoiceType.SYS_ERR);
230         } else if ("System.out".equalsIgnoreCase(logFile)) {
231             return new OutputChoice(cacheOutputStream ? OutputChoiceType.CACHED_SYS_OUT : OutputChoiceType.SYS_OUT);
232         } else {
233             try {
234                 FileOutputStream fos = new FileOutputStream(logFile, true);
235                 PrintStream printStream = new PrintStream(fos);
236                 return new OutputChoice(printStream);
237             } catch (FileNotFoundException e) {
238                 Reporter.error("Could not open [" + logFile + "]. Defaulting to System.err", e);
239                 return new OutputChoice(OutputChoiceType.SYS_ERR);
240             }
241         }
242     }
243 }