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