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.BufferedOutputStream;
20 import java.io.File;
21 import java.io.FileNotFoundException;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.OutputStream;
25 import java.io.Serializable;
26 import java.nio.channels.FileChannel;
27 import java.nio.channels.FileLock;
28 import java.util.HashMap;
29 import java.util.Map;
30
31 import org.apache.logging.log4j.core.Layout;
32
33
34
35
36
37 public class FileManager extends OutputStreamManager {
38
39 private static final FileManagerFactory FACTORY = new FileManagerFactory();
40
41 private final boolean isAppend;
42 private final boolean isLocking;
43 private final String advertiseURI;
44 private final int bufferSize;
45
46 protected FileManager(final String fileName, final OutputStream os, final boolean append, final boolean locking,
47 final String advertiseURI, final Layout<? extends Serializable> layout, final int bufferSize,
48 final boolean writeHeader) {
49 super(os, fileName, layout, writeHeader);
50 this.isAppend = append;
51 this.isLocking = locking;
52 this.advertiseURI = advertiseURI;
53 this.bufferSize = bufferSize;
54 }
55
56
57
58
59
60
61
62
63
64
65
66
67 public static FileManager getFileManager(final String fileName, final boolean append, boolean locking,
68 final boolean bufferedIo, final String advertiseUri, final Layout<? extends Serializable> layout,
69 final int bufferSize) {
70
71 if (locking && bufferedIo) {
72 locking = false;
73 }
74 return (FileManager) getManager(fileName, new FactoryData(append, locking, bufferedIo, bufferSize,
75 advertiseUri, layout), FACTORY);
76 }
77
78 @Override
79 protected synchronized void write(final byte[] bytes, final int offset, final int length) {
80
81 if (isLocking) {
82 final FileChannel channel = ((FileOutputStream) getOutputStream()).getChannel();
83 try {
84
85
86
87
88
89
90
91 final FileLock lock = channel.lock(0, Long.MAX_VALUE, false);
92 try {
93 super.write(bytes, offset, length);
94 } finally {
95 lock.release();
96 }
97 } catch (final IOException ex) {
98 throw new AppenderLoggingException("Unable to obtain lock on " + getName(), ex);
99 }
100
101 } else {
102 super.write(bytes, offset, length);
103 }
104 }
105
106
107
108
109
110 public String getFileName() {
111 return getName();
112 }
113
114
115
116
117
118 public boolean isAppend() {
119 return isAppend;
120 }
121
122
123
124
125
126 public boolean isLocking() {
127 return isLocking;
128 }
129
130
131
132
133
134
135 public int getBufferSize() {
136 return bufferSize;
137 }
138
139
140
141
142
143
144 @Override
145 public Map<String, String> getContentFormat() {
146 final Map<String, String> result = new HashMap<>(super.getContentFormat());
147 result.put("fileURI", advertiseURI);
148 return result;
149 }
150
151
152
153
154 private static class FactoryData {
155 private final boolean append;
156 private final boolean locking;
157 private final boolean bufferedIO;
158 private final int bufferSize;
159 private final String advertiseURI;
160 private final Layout<? extends Serializable> layout;
161
162
163
164
165
166
167
168
169
170 public FactoryData(final boolean append, final boolean locking, final boolean bufferedIO, final int bufferSize,
171 final String advertiseURI, final Layout<? extends Serializable> layout) {
172 this.append = append;
173 this.locking = locking;
174 this.bufferedIO = bufferedIO;
175 this.bufferSize = bufferSize;
176 this.advertiseURI = advertiseURI;
177 this.layout = layout;
178 }
179 }
180
181
182
183
184 private static class FileManagerFactory implements ManagerFactory<FileManager, FactoryData> {
185
186
187
188
189
190
191
192 @Override
193 public FileManager createManager(final String name, final FactoryData data) {
194 final File file = new File(name);
195 final File parent = file.getParentFile();
196 if (null != parent && !parent.exists()) {
197 parent.mkdirs();
198 }
199
200 final boolean writeHeader = !data.append || !file.exists();
201 OutputStream os;
202 try {
203 os = new FileOutputStream(name, data.append);
204 int bufferSize = data.bufferSize;
205 if (data.bufferedIO) {
206 os = new BufferedOutputStream(os, bufferSize);
207 } else {
208 bufferSize = -1;
209 }
210 return new FileManager(name, os, data.append, data.locking, data.advertiseURI, data.layout, bufferSize,
211 writeHeader);
212 } catch (final FileNotFoundException ex) {
213 LOGGER.error("FileManager (" + name + ") " + ex, ex);
214 }
215 return null;
216 }
217 }
218
219 }