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