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 @PluginBuilderAttribute
74 private String filePermissions;
75
76 @PluginBuilderAttribute
77 private String fileOwner;
78
79 @PluginBuilderAttribute
80 private String fileGroup;
81
82 @Override
83 public FileAppender build() {
84 boolean bufferedIo = isBufferedIo();
85 final int bufferSize = getBufferSize();
86 if (locking && bufferedIo) {
87 LOGGER.warn("Locking and buffering are mutually exclusive. No buffering will occur for {}", fileName);
88 bufferedIo = false;
89 }
90 if (!bufferedIo && bufferSize > 0) {
91 LOGGER.warn("The bufferSize is set to {} but bufferedIo is false: {}", bufferSize, bufferedIo);
92 }
93 final Layout<? extends Serializable> layout = getOrCreateLayout();
94
95 final FileManager manager = FileManager.getFileManager(fileName, append, locking, bufferedIo, createOnDemand,
96 advertiseUri, layout, bufferSize, filePermissions, fileOwner, fileGroup, getConfiguration());
97 if (manager == null) {
98 return null;
99 }
100
101 return new FileAppender(getName(), layout, getFilter(), manager, fileName, isIgnoreExceptions(),
102 !bufferedIo || isImmediateFlush(), advertise ? getConfiguration().getAdvertiser() : null);
103 }
104
105 public String getAdvertiseUri() {
106 return advertiseUri;
107 }
108
109 public String getFileName() {
110 return fileName;
111 }
112
113 public boolean isAdvertise() {
114 return advertise;
115 }
116
117 public boolean isAppend() {
118 return append;
119 }
120
121 public boolean isCreateOnDemand() {
122 return createOnDemand;
123 }
124
125 public boolean isLocking() {
126 return locking;
127 }
128
129 public String getFilePermissions() {
130 return filePermissions;
131 }
132
133 public String getFileOwner() {
134 return fileOwner;
135 }
136
137 public String getFileGroup() {
138 return fileGroup;
139 }
140
141 public B withAdvertise(final boolean advertise) {
142 this.advertise = advertise;
143 return asBuilder();
144 }
145
146 public B withAdvertiseUri(final String advertiseUri) {
147 this.advertiseUri = advertiseUri;
148 return asBuilder();
149 }
150
151 public B withAppend(final boolean append) {
152 this.append = append;
153 return asBuilder();
154 }
155
156 public B withFileName(final String fileName) {
157 this.fileName = fileName;
158 return asBuilder();
159 }
160
161 public B withCreateOnDemand(final boolean createOnDemand) {
162 this.createOnDemand = createOnDemand;
163 return asBuilder();
164 }
165
166 public B withLocking(final boolean locking) {
167 this.locking = locking;
168 return asBuilder();
169 }
170
171 public B withFilePermissions(final String filePermissions) {
172 this.filePermissions = filePermissions;
173 return asBuilder();
174 }
175
176 public B withFileOwner(final String fileOwner) {
177 this.fileOwner = fileOwner;
178 return asBuilder();
179 }
180
181 public B withFileGroup(final String fileGroup) {
182 this.fileGroup = fileGroup;
183 return asBuilder();
184 }
185
186 }
187
188 private static final int DEFAULT_BUFFER_SIZE = 8192;
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212 @Deprecated
213 public static <B extends Builder<B>> FileAppender createAppender(
214
215 final String fileName,
216 final String append,
217 final String locking,
218 final String name,
219 final String immediateFlush,
220 final String ignoreExceptions,
221 final String bufferedIo,
222 final String bufferSizeStr,
223 final Layout<? extends Serializable> layout,
224 final Filter filter,
225 final String advertise,
226 final String advertiseUri,
227 final Configuration config) {
228 return FileAppender.<B>newBuilder()
229 .withAdvertise(Boolean.parseBoolean(advertise))
230 .withAdvertiseUri(advertiseUri)
231 .withAppend(Booleans.parseBoolean(append, true))
232 .withBufferedIo(Booleans.parseBoolean(bufferedIo, true))
233 .withBufferSize(Integers.parseInt(bufferSizeStr, DEFAULT_BUFFER_SIZE))
234 .setConfiguration(config)
235 .withFileName(fileName)
236 .withFilter(filter)
237 .withIgnoreExceptions(Booleans.parseBoolean(ignoreExceptions, true))
238 .withImmediateFlush(Booleans.parseBoolean(immediateFlush, true))
239 .withLayout(layout)
240 .withLocking(Boolean.parseBoolean(locking))
241 .withName(name)
242 .build();
243
244 }
245
246 @PluginBuilderFactory
247 public static <B extends Builder<B>> B newBuilder() {
248 return new Builder<B>().asBuilder();
249 }
250
251 private final String fileName;
252
253 private final Advertiser advertiser;
254
255 private final Object advertisement;
256
257 private FileAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
258 final FileManager manager, final String filename, final boolean ignoreExceptions,
259 final boolean immediateFlush, final Advertiser advertiser) {
260
261 super(name, layout, filter, ignoreExceptions, immediateFlush, manager);
262 if (advertiser != null) {
263 final Map<String, String> configuration = new HashMap<>(layout.getContentFormat());
264 configuration.putAll(manager.getContentFormat());
265 configuration.put("contentType", layout.getContentType());
266 configuration.put("name", name);
267 advertisement = advertiser.advertise(configuration);
268 } else {
269 advertisement = null;
270 }
271 this.fileName = filename;
272 this.advertiser = advertiser;
273 }
274
275
276
277
278
279 public String getFileName() {
280 return this.fileName;
281 }
282
283 @Override
284 public boolean stop(final long timeout, final TimeUnit timeUnit) {
285 setStopping();
286 super.stop(timeout, timeUnit, false);
287 if (advertiser != null) {
288 advertiser.unadvertise(advertisement);
289 }
290 setStopped();
291 return true;
292 }
293 }