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 java.io.Serializable;
20 import java.util.HashMap;
21 import java.util.Map;
22 import java.util.concurrent.TimeUnit;
23
24 import org.apache.logging.log4j.core.Appender;
25 import org.apache.logging.log4j.core.Core;
26 import org.apache.logging.log4j.core.Filter;
27 import org.apache.logging.log4j.core.Layout;
28 import org.apache.logging.log4j.core.config.Configuration;
29 import org.apache.logging.log4j.core.config.plugins.Plugin;
30 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
31 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
32 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
33 import org.apache.logging.log4j.core.net.Advertiser;
34 import org.apache.logging.log4j.core.util.Booleans;
35 import org.apache.logging.log4j.core.util.Integers;
36
37
38
39
40 @Plugin(name = FileAppender.PLUGIN_NAME, category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true)
41 public final class FileAppender extends AbstractOutputStreamAppender<FileManager> {
42
43 public static final String PLUGIN_NAME = "File";
44
45
46
47
48
49
50
51 public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B>
52 implements org.apache.logging.log4j.core.util.Builder<FileAppender> {
53
54 @PluginBuilderAttribute
55 @Required
56 private String fileName;
57
58 @PluginBuilderAttribute
59 private boolean append = true;
60
61 @PluginBuilderAttribute
62 private boolean locking;
63
64 @PluginBuilderAttribute
65 private boolean advertise;
66
67 @PluginBuilderAttribute
68 private String advertiseUri;
69
70 @PluginBuilderAttribute
71 private boolean createOnDemand;
72
73 @Override
74 public FileAppender build() {
75 boolean bufferedIo = isBufferedIo();
76 final int bufferSize = getBufferSize();
77 if (locking && bufferedIo) {
78 LOGGER.warn("Locking and buffering are mutually exclusive. No buffering will occur for {}", fileName);
79 bufferedIo = false;
80 }
81 if (!bufferedIo && bufferSize > 0) {
82 LOGGER.warn("The bufferSize is set to {} but bufferedIo is false: {}", bufferSize, bufferedIo);
83 }
84 final Layout<? extends Serializable> layout = getOrCreateLayout();
85
86 final FileManager manager = FileManager.getFileManager(fileName, append, locking, bufferedIo, createOnDemand,
87 advertiseUri, layout, bufferSize, getConfiguration());
88 if (manager == null) {
89 return null;
90 }
91
92 return new FileAppender(getName(), layout, getFilter(), manager, fileName, isIgnoreExceptions(),
93 !bufferedIo || isImmediateFlush(), advertise ? getConfiguration().getAdvertiser() : null);
94 }
95
96 public String getAdvertiseUri() {
97 return advertiseUri;
98 }
99
100 public String getFileName() {
101 return fileName;
102 }
103
104 public boolean isAdvertise() {
105 return advertise;
106 }
107
108 public boolean isAppend() {
109 return append;
110 }
111
112 public boolean isCreateOnDemand() {
113 return createOnDemand;
114 }
115
116 public boolean isLocking() {
117 return locking;
118 }
119
120 public B withAdvertise(final boolean advertise) {
121 this.advertise = advertise;
122 return asBuilder();
123 }
124
125 public B withAdvertiseUri(final String advertiseUri) {
126 this.advertiseUri = advertiseUri;
127 return asBuilder();
128 }
129
130 public B withAppend(final boolean append) {
131 this.append = append;
132 return asBuilder();
133 }
134
135 public B withFileName(final String fileName) {
136 this.fileName = fileName;
137 return asBuilder();
138 }
139
140 public B withCreateOnDemand(final boolean createOnDemand) {
141 this.createOnDemand = createOnDemand;
142 return asBuilder();
143 }
144
145 public B withLocking(final boolean locking) {
146 this.locking = locking;
147 return asBuilder();
148 }
149
150 }
151
152 private static final int DEFAULT_BUFFER_SIZE = 8192;
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176 @Deprecated
177 public static <B extends Builder<B>> FileAppender createAppender(
178
179 final String fileName,
180 final String append,
181 final String locking,
182 final String name,
183 final String immediateFlush,
184 final String ignoreExceptions,
185 final String bufferedIo,
186 final String bufferSizeStr,
187 final Layout<? extends Serializable> layout,
188 final Filter filter,
189 final String advertise,
190 final String advertiseUri,
191 final Configuration config) {
192 return FileAppender.<B>newBuilder()
193 .withAdvertise(Boolean.parseBoolean(advertise))
194 .withAdvertiseUri(advertiseUri)
195 .withAppend(Booleans.parseBoolean(append, true))
196 .withBufferedIo(Booleans.parseBoolean(bufferedIo, true))
197 .withBufferSize(Integers.parseInt(bufferSizeStr, DEFAULT_BUFFER_SIZE))
198 .setConfiguration(config)
199 .withFileName(fileName)
200 .withFilter(filter)
201 .withIgnoreExceptions(Booleans.parseBoolean(ignoreExceptions, true))
202 .withImmediateFlush(Booleans.parseBoolean(immediateFlush, true))
203 .withLayout(layout)
204 .withLocking(Boolean.parseBoolean(locking))
205 .withName(name)
206 .build();
207
208 }
209
210 @PluginBuilderFactory
211 public static <B extends Builder<B>> B newBuilder() {
212 return new Builder<B>().asBuilder();
213 }
214
215 private final String fileName;
216
217 private final Advertiser advertiser;
218
219 private final Object advertisement;
220
221 private FileAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
222 final FileManager manager, final String filename, final boolean ignoreExceptions,
223 final boolean immediateFlush, final Advertiser advertiser) {
224
225 super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
226 if (advertiser != null) {
227 final Map<String, String> configuration = new HashMap<>(layout.getContentFormat());
228 configuration.putAll(manager.getContentFormat());
229 configuration.put("contentType", layout.getContentType());
230 configuration.put("name", name);
231 advertisement = advertiser.advertise(configuration);
232 } else {
233 advertisement = null;
234 }
235 this.fileName = filename;
236 this.advertiser = advertiser;
237 }
238
239
240
241
242
243 public String getFileName() {
244 return this.fileName;
245 }
246
247 @Override
248 public boolean stop(final long timeout, final TimeUnit timeUnit) {
249 setStopping();
250 super.stop(timeout, timeUnit, false);
251 if (advertiser != null) {
252 advertiser.unadvertise(advertisement);
253 }
254 setStopped();
255 return true;
256 }
257 }