View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core;
15  
16  import java.io.OutputStream;
17  import java.io.PrintStream;
18  import java.lang.reflect.Method;
19  import java.util.Arrays;
20  
21  import ch.qos.logback.core.joran.spi.ConsoleTarget;
22  import ch.qos.logback.core.status.Status;
23  import ch.qos.logback.core.status.WarnStatus;
24  import ch.qos.logback.core.util.Loader;
25  
26  /**
27   * ConsoleAppender appends log events to <code>System.out</code> or
28   * <code>System.err</code> using a layout specified by the user. The default
29   * target is <code>System.out</code>.
30   * <p>
31   * &nbsp;
32   * </p>
33   * For more information about this appender, please refer to the online manual
34   * at http://logback.qos.ch/manual/appenders.html#ConsoleAppender
35   *
36   * @author Ceki G&uuml;lc&uuml;
37   * @author Tom SH Liu
38   * @author Ruediger Dohna
39   */
40  
41  public class ConsoleAppender<E> extends OutputStreamAppender<E> {
42  
43      protected ConsoleTarget target = ConsoleTarget.SystemOut;
44      protected boolean withJansi = false;
45  
46      private final static String AnsiConsole_CLASS_NAME = "org.fusesource.jansi.AnsiConsole";
47      private final static String wrapSystemOut_METHOD_NAME = "wrapSystemOut";
48      private final static String wrapSystemErr_METHOD_NAME = "wrapSystemErr";
49      private final static Class<?>[] ARGUMENT_TYPES = { PrintStream.class };
50  
51      /**
52       * Sets the value of the <b>Target</b> option. Recognized values are
53       * "System.out" and "System.err". Any other value will be ignored.
54       */
55      public void setTarget(String value) {
56          ConsoleTarget t = ConsoleTarget.findByName(value.trim());
57          if (t == null) {
58              targetWarn(value);
59          } else {
60              target = t;
61          }
62      }
63  
64      /**
65       * Returns the current value of the <b>target</b> property. The default value of
66       * the option is "System.out".
67       * <p>
68       * See also {@link #setTarget}.
69       */
70      public String getTarget() {
71          return target.getName();
72      }
73  
74      private void targetWarn(String val) {
75          Status status = new WarnStatus("[" + val + "] should be one of " + Arrays.toString(ConsoleTarget.values()),
76                  this);
77          status.add(new WarnStatus("Using previously set target, System.out by default.", this));
78          addStatus(status);
79      }
80  
81      @Override
82      public void start() {
83          OutputStream targetStream = target.getStream();
84          // enable jansi only if withJansi set to true
85          if (withJansi) {
86              targetStream = wrapWithJansi(targetStream);
87          }
88          setOutputStream(targetStream);
89          super.start();
90      }
91  
92      private OutputStream wrapWithJansi(OutputStream targetStream) {
93          try {
94              addInfo("Enabling JANSI AnsiPrintStream for the console.");
95              ClassLoader classLoader = Loader.getClassLoaderOfObject(context);
96              Class<?> classObj = classLoader.loadClass(AnsiConsole_CLASS_NAME);
97              String methodName = target == ConsoleTarget.SystemOut ? wrapSystemOut_METHOD_NAME
98                      : wrapSystemErr_METHOD_NAME;
99              Method method = classObj.getMethod(methodName, ARGUMENT_TYPES);
100             return (OutputStream) method.invoke(null, new PrintStream(targetStream));
101         } catch (Exception e) {
102             addWarn("Failed to create AnsiPrintStream. Falling back on the default stream.", e);
103         }
104         return targetStream;
105     }
106 
107     /**
108      * @return whether to use JANSI or not.
109      */
110     public boolean isWithJansi() {
111         return withJansi;
112     }
113 
114     /**
115      * If true, this appender will output to a stream provided by the JANSI library.
116      *
117      * @param withJansi whether to use JANSI or not.
118      * @since 1.0.5
119      */
120     public void setWithJansi(boolean withJansi) {
121         this.withJansi = withJansi;
122     }
123 
124 }