1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.logging.log4j.core.config.status;
19
20 import java.io.File;
21 import java.io.FileNotFoundException;
22 import java.io.FileOutputStream;
23 import java.io.PrintStream;
24 import java.net.URI;
25 import java.net.URISyntaxException;
26 import java.util.Collection;
27 import java.util.concurrent.LinkedBlockingQueue;
28
29 import org.apache.logging.log4j.Level;
30 import org.apache.logging.log4j.core.util.FileUtils;
31 import org.apache.logging.log4j.core.util.NetUtils;
32 import org.apache.logging.log4j.status.StatusConsoleListener;
33 import org.apache.logging.log4j.status.StatusListener;
34 import org.apache.logging.log4j.status.StatusLogger;
35
36
37
38
39 public class StatusConfiguration {
40
41 @SuppressWarnings("UseOfSystemOutOrSystemErr")
42 private static final PrintStream DEFAULT_STREAM = System.out;
43 private static final Level DEFAULT_STATUS = Level.ERROR;
44 private static final Verbosity DEFAULT_VERBOSITY = Verbosity.QUIET;
45
46 private final Collection<String> errorMessages = new LinkedBlockingQueue<String>();
47 private final StatusLogger logger = StatusLogger.getLogger();
48
49 private volatile boolean initialized = false;
50
51 private PrintStream destination = DEFAULT_STREAM;
52 private Level status = DEFAULT_STATUS;
53 private Verbosity verbosity = DEFAULT_VERBOSITY;
54 private String[] verboseClasses;
55
56
57
58
59 public enum Verbosity {
60 QUIET, VERBOSE;
61
62
63
64
65
66
67
68 public static Verbosity toVerbosity(final String value) {
69 return Boolean.parseBoolean(value) ? VERBOSE : QUIET;
70 }
71 }
72
73
74
75
76
77
78
79 public void error(final String message) {
80 if (!this.initialized) {
81 this.errorMessages.add(message);
82 } else {
83 this.logger.error(message);
84 }
85 }
86
87
88
89
90
91
92
93
94
95
96 public StatusConfiguration withDestination(final String destination) {
97 try {
98 this.destination = parseStreamName(destination);
99 } catch (final URISyntaxException e) {
100 this.error("Could not parse URI [" + destination + "]. Falling back to default of stdout.");
101 this.destination = DEFAULT_STREAM;
102 } catch (final FileNotFoundException e) {
103 this.error("File could not be found at [" + destination + "]. Falling back to default of stdout.");
104 this.destination = DEFAULT_STREAM;
105 }
106 return this;
107 }
108
109 private PrintStream parseStreamName(final String name) throws URISyntaxException, FileNotFoundException {
110 if (name == null || name.equalsIgnoreCase("out")) {
111 return DEFAULT_STREAM;
112 }
113 if (name.equalsIgnoreCase("err")) {
114 return System.err;
115 }
116 final URI destUri = NetUtils.toURI(name);
117 final File output = FileUtils.fileFromUri(destUri);
118 if (output == null) {
119
120 return DEFAULT_STREAM;
121 }
122 final FileOutputStream fos = new FileOutputStream(output);
123 return new PrintStream(fos, true);
124 }
125
126
127
128
129
130
131
132
133 public StatusConfiguration withStatus(final String status) {
134 this.status = Level.toLevel(status, null);
135 if (this.status == null) {
136 this.error("Invalid status level specified: " + status + ". Defaulting to ERROR.");
137 this.status = Level.ERROR;
138 }
139 return this;
140 }
141
142
143
144
145
146
147
148 public StatusConfiguration withStatus(final Level status) {
149 this.status = status;
150 return this;
151 }
152
153
154
155
156
157
158
159
160 public StatusConfiguration withVerbosity(final String verbosity) {
161 this.verbosity = Verbosity.toVerbosity(verbosity);
162 return this;
163 }
164
165
166
167
168
169
170
171 public StatusConfiguration withVerboseClasses(final String... verboseClasses) {
172 this.verboseClasses = verboseClasses;
173 return this;
174 }
175
176
177
178
179 public void initialize() {
180 if (!this.initialized) {
181 if (this.status == Level.OFF) {
182 this.initialized = true;
183 } else {
184 final boolean configured = configureExistingStatusConsoleListener();
185 if (!configured) {
186 registerNewStatusConsoleListener();
187 }
188 migrateSavedLogMessages();
189 }
190 }
191 }
192
193 private boolean configureExistingStatusConsoleListener() {
194 boolean configured = false;
195 for (final StatusListener statusListener : this.logger.getListeners()) {
196 if (statusListener instanceof StatusConsoleListener) {
197 final StatusConsoleListener listener = (StatusConsoleListener) statusListener;
198 listener.setLevel(this.status);
199 this.logger.updateListenerLevel(this.status);
200 if (this.verbosity == Verbosity.QUIET) {
201 listener.setFilters(this.verboseClasses);
202 }
203 configured = true;
204 }
205 }
206 return configured;
207 }
208
209
210 private void registerNewStatusConsoleListener() {
211 final StatusConsoleListener listener = new StatusConsoleListener(this.status, this.destination);
212 if (this.verbosity == Verbosity.QUIET) {
213 listener.setFilters(this.verboseClasses);
214 }
215 this.logger.registerListener(listener);
216 }
217
218 private void migrateSavedLogMessages() {
219 for (final String message : this.errorMessages) {
220 this.logger.error(message);
221 }
222 this.initialized = true;
223 this.errorMessages.clear();
224 }
225 }