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