1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.appender;
18
19 import org.apache.logging.log4j.core.Filter;
20 import org.apache.logging.log4j.core.Layout;
21 import org.apache.logging.log4j.core.config.plugins.Plugin;
22 import org.apache.logging.log4j.core.config.plugins.PluginAttr;
23 import org.apache.logging.log4j.core.config.plugins.PluginElement;
24 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
25 import org.apache.logging.log4j.core.helpers.Loader;
26 import org.apache.logging.log4j.core.layout.PatternLayout;
27 import org.apache.logging.log4j.util.PropertiesUtil;
28
29 import java.io.IOException;
30 import java.io.OutputStream;
31 import java.io.PrintStream;
32 import java.lang.reflect.Constructor;
33
34
35
36
37
38
39
40
41
42
43
44 @Plugin(name = "Console", type = "Core", elementType = "appender", printObject = true)
45 public final class ConsoleAppender extends AbstractOutputStreamAppender {
46
47 private static ConsoleManagerFactory factory = new ConsoleManagerFactory();
48
49
50
51
52 public enum Target {
53
54 SYSTEM_OUT,
55
56 SYSTEM_ERR
57 }
58
59 private ConsoleAppender(final String name, final Layout layout, final Filter filter,
60 final OutputStreamManager manager,
61 final boolean handleExceptions) {
62 super(name, layout, filter, handleExceptions, true, manager);
63 }
64
65
66
67
68
69
70
71
72
73
74
75
76 @PluginFactory
77 public static ConsoleAppender createAppender(@PluginElement("layout") Layout layout,
78 @PluginElement("filters") final Filter filter,
79 @PluginAttr("target") final String t,
80 @PluginAttr("name") final String name,
81 @PluginAttr("follow") final String follow,
82 @PluginAttr("suppressExceptions") final String suppress) {
83 if (name == null) {
84 LOGGER.error("No name provided for ConsoleAppender");
85 return null;
86 }
87 if (layout == null) {
88 layout = PatternLayout.createLayout(null, null, null, null);
89 }
90 final boolean isFollow = follow == null ? false : Boolean.valueOf(follow);
91 final boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
92 final Target target = t == null ? Target.SYSTEM_OUT : Target.valueOf(t);
93 return new ConsoleAppender(name, layout, filter, getManager(isFollow, target), handleExceptions);
94 }
95
96 private static OutputStreamManager getManager(final boolean follow, final Target target) {
97 final String type = target.name();
98 final OutputStream os = getOutputStream(follow, target);
99 return OutputStreamManager.getManager(target.name() + "." + follow, new FactoryData(os, type), factory);
100 }
101
102 private static OutputStream getOutputStream(final boolean follow, final Target target) {
103 final PrintStream printStream = target == Target.SYSTEM_OUT ?
104 follow ? new PrintStream(new SystemOutStream()) : System.out :
105 follow ? new PrintStream(new SystemErrStream()) : System.err;
106 PropertiesUtil propsUtil = PropertiesUtil.getProperties();
107 if (!propsUtil.getStringProperty("os.name").startsWith("Windows") ||
108 propsUtil.getBooleanProperty("log4j.skipJansi")) {
109 return printStream;
110 } else {
111 try {
112 final ClassLoader loader = Loader.getClassLoader();
113
114 final Class<?> clazz = loader.loadClass("org.fusesource.jansi.WindowsAnsiOutputStream");
115 final Constructor<?> constructor = clazz.getConstructor(OutputStream.class);
116 return (OutputStream) constructor.newInstance(printStream);
117 } catch (final ClassNotFoundException cnfe) {
118 LOGGER.debug("Jansi is not installed");
119 } catch (final NoSuchMethodException nsme) {
120 LOGGER.warn("WindowsAnsiOutputStream is missing the proper constructor");
121 } catch (final Exception ex) {
122 LOGGER.warn("Unable to instantiate WindowsAnsiOutputStream");
123 }
124 return printStream;
125 }
126 }
127
128
129
130
131
132
133 private static class SystemErrStream extends OutputStream {
134 public SystemErrStream() {
135 }
136
137 @Override
138 public void close() {
139 }
140
141 @Override
142 public void flush() {
143 System.err.flush();
144 }
145
146 @Override
147 public void write(final byte[] b) throws IOException {
148 System.err.write(b);
149 }
150
151 @Override
152 public void write(final byte[] b, final int off, final int len)
153 throws IOException {
154 System.err.write(b, off, len);
155 }
156
157 @Override
158 public void write(final int b) {
159 System.err.write(b);
160 }
161 }
162
163
164
165
166
167
168 private static class SystemOutStream extends OutputStream {
169 public SystemOutStream() {
170 }
171
172 @Override
173 public void close() {
174 }
175
176 @Override
177 public void flush() {
178 System.out.flush();
179 }
180
181 @Override
182 public void write(final byte[] b) throws IOException {
183 System.out.write(b);
184 }
185
186 @Override
187 public void write(final byte[] b, final int off, final int len)
188 throws IOException {
189 System.out.write(b, off, len);
190 }
191
192 @Override
193 public void write(final int b) throws IOException {
194 System.out.write(b);
195 }
196 }
197
198
199
200
201 private static class FactoryData {
202 private final OutputStream os;
203 private final String type;
204
205
206
207
208
209
210 public FactoryData(final OutputStream os, final String type) {
211 this.os = os;
212 this.type = type;
213 }
214 }
215
216
217
218
219 private static class ConsoleManagerFactory implements ManagerFactory<OutputStreamManager, FactoryData> {
220
221
222
223
224
225
226
227 public OutputStreamManager createManager(final String name, final FactoryData data) {
228 return new OutputStreamManager(data.os, data.type);
229 }
230 }
231
232 }