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