View Javadoc
1   /*
2    * Copyright (c) 2012-present Sonatype, Inc. All rights reserved.
3    *
4    * This program is licensed to you under the Apache License Version 2.0,
5    * and you may not use this file except in compliance with the Apache License Version 2.0.
6    * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
7    *
8    * Unless required by applicable law or agreed to in writing,
9    * software distributed under the Apache License Version 2.0 is distributed on an
10   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11   * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
12   */
13  package org.sonatype.install4j.slf4j;
14  
15  import java.io.InputStream;
16  import java.net.URL;
17  import java.security.AccessController;
18  import java.security.PrivilegedAction;
19  import java.util.Properties;
20  
21  import com.install4j.api.Util;
22  import com.install4j.api.actions.Action;
23  import com.install4j.api.screens.Screen;
24  import org.slf4j.Logger;
25  import org.slf4j.helpers.FormattingTuple;
26  import org.slf4j.helpers.MarkerIgnoringBase;
27  import org.slf4j.helpers.MessageFormatter;
28  import org.slf4j.spi.LocationAwareLogger;
29  
30  // Based in slf4j SimpleLogger
31  
32  /**
33   * install4j-slf4j bridge {@link Logger}.
34   *
35   * @since 1.0
36   */
37  public class Install4jLogger
38      extends MarkerIgnoringBase
39  {
40    private static final long serialVersionUID = 1;
41  
42    private static final String CONFIGURATION_FILE = "install4jlogger.properties";
43  
44    private static final String CONFIGURATION_PREFIX = Install4jLogger.class.getPackage().getName() + ".";
45  
46    public static final int LEVEL_TRACE = LocationAwareLogger.TRACE_INT;
47  
48    public static final int LEVEL_DEBUG = LocationAwareLogger.DEBUG_INT;
49  
50    public static final int LEVEL_INFO = LocationAwareLogger.INFO_INT;
51  
52    public static final int LEVEL_WARN = LocationAwareLogger.WARN_INT;
53  
54    public static final int LEVEL_ERROR = LocationAwareLogger.ERROR_INT;
55  
56    public static final int LEVEL_ALL = (LEVEL_TRACE - 10);
57  
58    public static final int LEVEL_OFF = (LEVEL_ERROR + 10);
59  
60    private static final Properties configuration = new Properties();
61  
62    private static boolean showLogName = true;
63  
64    private static boolean showLevel = false;
65  
66    private static String getStringProperty(final String name) {
67      String prop = null;
68      try {
69        prop = System.getProperty(name);
70      }
71      catch (SecurityException e) {
72        // Ignore
73      }
74      return (prop == null) ? configuration.getProperty(name) : prop;
75    }
76  
77    //private static String getStringProperty(final String name, final String defaultValue) {
78    //    String prop = getStringProperty(name);
79    //    return (prop == null) ? defaultValue : prop;
80    //}
81  
82    private static boolean getBooleanProperty(final String name, final boolean defaultValue) {
83      String prop = getStringProperty(name);
84      return (prop == null) ? defaultValue : "true".equalsIgnoreCase(prop);
85    }
86  
87    static {
88      URL url = (URL) AccessController.doPrivileged(
89          new PrivilegedAction()
90          {
91            public Object run() {
92              ClassLoader threadCL = Thread.currentThread().getContextClassLoader();
93              if (threadCL != null) {
94                return threadCL.getResource(CONFIGURATION_FILE);
95              }
96              else {
97                return ClassLoader.getSystemResource(CONFIGURATION_FILE);
98              }
99            }
100         });
101 
102     if (url != null) {
103       try {
104         Util.logInfo(null, "Reading " + CONFIGURATION_FILE + ": " + url);
105         InputStream input = url.openStream();
106         try {
107           configuration.load(input);
108           Util.logInfo(null, "Configuration: " + configuration);
109         }
110         finally {
111           input.close();
112         }
113       }
114       catch (java.io.IOException e) {
115         Util.logError(null, "Failed to load: " + CONFIGURATION_FILE);
116         Util.log(e);
117       }
118     }
119     else {
120       Util.logError(null, "Missing: " + CONFIGURATION_FILE);
121     }
122 
123     showLogName = getBooleanProperty(CONFIGURATION_PREFIX + "showLogName", showLogName);
124     Util.logInfo(null, "Show log-name: " + showLogName);
125 
126     showLevel = getBooleanProperty(CONFIGURATION_PREFIX + "showLevel", showLevel);
127     Util.logInfo(null, "Show level: " + showLevel);
128   }
129 
130   protected int currentLogLevel = LEVEL_INFO;
131 
132   private Class type;
133 
134   private boolean screenOrAction = false;
135 
136   Install4jLogger(String name) {
137     this.name = name;
138 
139     // install4j's Util.log* helpers need a type (or object) to determine name, so try and load the type here
140     this.type = loadType();
141     if (type != null) {
142       screenOrAction = Screen.class.isAssignableFrom(type) || Action.class.isAssignableFrom(type);
143     }
144 
145     // Set log level from properties
146     String level = getStringProperty(CONFIGURATION_PREFIX + "logger." + name);
147     int i = name.lastIndexOf(".");
148     while (null == level && i > -1) {
149       name = name.substring(0, i);
150       level = getStringProperty(CONFIGURATION_PREFIX + "logger." + name);
151       i = name.lastIndexOf(".");
152     }
153 
154     if (null == level) {
155       level = getStringProperty(CONFIGURATION_PREFIX + "level");
156     }
157 
158     if ("all".equalsIgnoreCase(level)) {
159       this.currentLogLevel = LEVEL_ALL;
160     }
161     else if ("trace".equalsIgnoreCase(level)) {
162       this.currentLogLevel = LEVEL_TRACE;
163     }
164     else if ("debug".equalsIgnoreCase(level)) {
165       this.currentLogLevel = LEVEL_DEBUG;
166     }
167     else if ("info".equalsIgnoreCase(level)) {
168       this.currentLogLevel = LEVEL_INFO;
169     }
170     else if ("warn".equalsIgnoreCase(level)) {
171       this.currentLogLevel = LEVEL_WARN;
172     }
173     else if ("error".equalsIgnoreCase(level)) {
174       this.currentLogLevel = LEVEL_ERROR;
175     }
176     else if ("off".equalsIgnoreCase(level)) {
177       this.currentLogLevel = LEVEL_OFF;
178     }
179   }
180 
181   private Class loadType() {
182     try {
183       ClassLoader cl = Thread.currentThread().getContextClassLoader();
184       return cl.loadClass(name);
185     }
186     catch (Exception e) {
187       return null;
188     }
189   }
190 
191   private void log(final int level, final String message, final Throwable t) {
192     if (!isLevelEnabled(level)) {
193       return;
194     }
195 
196     StringBuilder buff = new StringBuilder(32);
197 
198     if (showLevel) {
199       switch (level) {
200         case LEVEL_TRACE:
201           buff.append("TRACE");
202           break;
203         case LEVEL_DEBUG:
204           buff.append("DEBUG");
205           break;
206         case LEVEL_INFO:
207           buff.append("INFO");
208           break;
209         case LEVEL_WARN:
210           buff.append("WARN");
211           break;
212         case LEVEL_ERROR:
213           buff.append("ERROR");
214           break;
215       }
216       buff.append(' ');
217     }
218 
219     // Only append name if no type associated
220     if (type == null && showLogName) {
221       buff.append(name).append(" - ");
222     }
223 
224     buff.append(message);
225 
226     // If the logger if for a screen or action, null the source to use the current (which should be the screen or action)
227     Object source = type;
228     if (screenOrAction) {
229       source = null;
230     }
231 
232     // Hand over the details to install4j's Util helper
233     if (level == LEVEL_ERROR) {
234       Util.logError(source, buff.toString());
235     }
236     else {
237       Util.logInfo(source, buff.toString());
238     }
239     if (t != null) {
240       Util.log(t);
241     }
242   }
243 
244   private void formatAndLog(int level, String format, Object arg1, Object arg2) {
245     if (!isLevelEnabled(level)) {
246       return;
247     }
248     FormattingTuple tp = MessageFormatter.format(format, arg1, arg2);
249     log(level, tp.getMessage(), tp.getThrowable());
250   }
251 
252   private void formatAndLog(int level, String format, Object[] argArray) {
253     if (!isLevelEnabled(level)) {
254       return;
255     }
256     FormattingTuple tp = MessageFormatter.arrayFormat(format, argArray);
257     log(level, tp.getMessage(), tp.getThrowable());
258   }
259 
260   protected boolean isLevelEnabled(int logLevel) {
261     return (logLevel >= currentLogLevel);
262   }
263 
264   public boolean isTraceEnabled() {
265     return isLevelEnabled(LEVEL_TRACE);
266   }
267 
268   public void trace(String msg) {
269     log(LEVEL_TRACE, msg, null);
270   }
271 
272   public void trace(String format, Object param1) {
273     formatAndLog(LEVEL_TRACE, format, param1, null);
274   }
275 
276   public void trace(String format, Object param1, Object param2) {
277     formatAndLog(LEVEL_TRACE, format, param1, param2);
278   }
279 
280   public void trace(String format, Object[] argArray) {
281     formatAndLog(LEVEL_TRACE, format, argArray);
282   }
283 
284   public void trace(String msg, Throwable t) {
285     log(LEVEL_TRACE, msg, t);
286   }
287 
288   public boolean isDebugEnabled() {
289     return isLevelEnabled(LEVEL_DEBUG);
290   }
291 
292   public void debug(String msg) {
293     log(LEVEL_DEBUG, msg, null);
294   }
295 
296   public void debug(String format, Object param1) {
297     formatAndLog(LEVEL_DEBUG, format, param1, null);
298   }
299 
300   public void debug(String format, Object param1, Object param2) {
301     formatAndLog(LEVEL_DEBUG, format, param1, param2);
302   }
303 
304   public void debug(String format, Object[] argArray) {
305     formatAndLog(LEVEL_DEBUG, format, argArray);
306   }
307 
308   public void debug(String msg, Throwable t) {
309     log(LEVEL_DEBUG, msg, t);
310   }
311 
312   public boolean isInfoEnabled() {
313     return isLevelEnabled(LEVEL_INFO);
314   }
315 
316   public void info(String msg) {
317     log(LEVEL_INFO, msg, null);
318   }
319 
320   public void info(String format, Object arg) {
321     formatAndLog(LEVEL_INFO, format, arg, null);
322   }
323 
324   public void info(String format, Object arg1, Object arg2) {
325     formatAndLog(LEVEL_INFO, format, arg1, arg2);
326   }
327 
328   public void info(String format, Object[] argArray) {
329     formatAndLog(LEVEL_INFO, format, argArray);
330   }
331 
332   public void info(String msg, Throwable t) {
333     log(LEVEL_INFO, msg, t);
334   }
335 
336   public boolean isWarnEnabled() {
337     return isLevelEnabled(LEVEL_WARN);
338   }
339 
340   public void warn(String msg) {
341     log(LEVEL_WARN, msg, null);
342   }
343 
344   public void warn(String format, Object arg) {
345     formatAndLog(LEVEL_WARN, format, arg, null);
346   }
347 
348   public void warn(String format, Object arg1, Object arg2) {
349     formatAndLog(LEVEL_WARN, format, arg1, arg2);
350   }
351 
352   public void warn(String format, Object[] argArray) {
353     formatAndLog(LEVEL_WARN, format, argArray);
354   }
355 
356   public void warn(String msg, Throwable t) {
357     log(LEVEL_WARN, msg, t);
358   }
359 
360   public boolean isErrorEnabled() {
361     return isLevelEnabled(LEVEL_ERROR);
362   }
363 
364   public void error(String msg) {
365     log(LEVEL_ERROR, msg, null);
366   }
367 
368   public void error(String format, Object arg) {
369     formatAndLog(LEVEL_ERROR, format, arg, null);
370   }
371 
372   public void error(String format, Object arg1, Object arg2) {
373     formatAndLog(LEVEL_ERROR, format, arg1, arg2);
374   }
375 
376   public void error(String format, Object[] argArray) {
377     formatAndLog(LEVEL_ERROR, format, argArray);
378   }
379 
380   public void error(String msg, Throwable t) {
381     log(LEVEL_ERROR, msg, t);
382   }
383 }