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