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