1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package net.sourceforge.acelogger.appender;
16
17 import java.io.File;
18 import java.io.FileOutputStream;
19 import java.io.RandomAccessFile;
20 import java.io.Writer;
21 import java.nio.channels.Channels;
22 import java.nio.channels.WritableByteChannel;
23 import java.text.MessageFormat;
24 import java.util.Date;
25
26 import net.sourceforge.acelogger.LogEvent;
27 import net.sourceforge.acelogger.execution.LogController;
28 import net.sourceforge.acelogger.execution.manager.ExecutorManager;
29 import net.sourceforge.acelogger.formatter.Formatter;
30
31
32 public class TextFileAppender extends BaseAppender {
33
34 private static final String DEFAULT_CHARSET = "UTF-8";
35
36 private static final String HEADER = "# {1}: created on {0,date,yyyy-MM-dd HH:mm:ss,SSS} by {2}\n";
37
38 private static final String FOOTER = "# last updated on {0,date,yyyy-MM-dd HH:mm:ss,SSS}\n";
39
40 private String fileName;
41
42 private WritableByteChannel fileChannel;
43
44 private Writer fileWriter;
45
46 private boolean newFile;
47
48 public TextFileAppender(String identifier, String fileName, Formatter formatter,
49 ExecutorManager executor) {
50 super(identifier, formatter, executor);
51 this.fileName = fileName;
52 newFile = false;
53 super.initialize();
54 }
55
56
57 private String getHeader() {
58 return MessageFormat.format(HEADER, new Date(), fileName, TextFileAppender.class);
59 }
60
61 private String getFooter() {
62 return MessageFormat.format(FOOTER, new Date(), fileName, TextFileAppender.class);
63 }
64
65
66 @Override
67 protected Runnable openProcess() {
68 final Runnable openFileProcess = new Runnable() {
69 public void run() {
70 try {
71 File file = new File(fileName);
72 if (!file.exists()) {
73 if (file.getParentFile() != null && !file.getParentFile().exists()) {
74 file.getParentFile().mkdirs();
75 }
76
77 newFile = file.createNewFile();
78 }
79 fileChannel = Channels.newChannel(new FileOutputStream(file, true));
80 fileWriter = Channels.newWriter(fileChannel, DEFAULT_CHARSET);
81 if (!newFile) {
82 RandomAccessFile f = new RandomAccessFile(file, "rw");
83 f.setLength(f.length() - getFooter().getBytes(DEFAULT_CHARSET).length);
84 f.close();
85 }
86 } catch (Exception e) {
87 LogController.getInternalLogger().error("Could not open file \"{0}\"",
88 e, fileName);
89 }
90 }
91 };
92 return openFileProcess;
93 }
94
95
96 @Override
97 public Runnable closeProcess() {
98 final Runnable closeFileProcess = new Runnable() {
99 public void run() {
100 try {
101 fileWriter.flush();
102 fileChannel.close();
103 } catch (Exception e) {
104 LogController.getInternalLogger().error("Could not close file \"{0}\"",
105 e, fileName);
106 }
107 }
108 };
109 return closeFileProcess;
110 }
111
112
113 @Override
114 public Runnable appendHeaderProcess() {
115 return new Runnable() {
116 public void run() {
117 try {
118 if (newFile) {
119 fileWriter.write(getHeader());
120 }
121 } catch (Exception e) {
122 LogController.getInternalLogger().error(
123 "Could not append header to file \"{0}\"", e, fileName);
124 }
125 }
126 };
127 }
128
129
130 @Override
131 public Runnable appendFooterProcess() {
132 return new Runnable() {
133 public void run() {
134 try {
135 fileWriter.write(getFooter());
136 } catch (Exception e) {
137 LogController.getInternalLogger().error(
138 "Could not append footer to file \"{0}\"", e, fileName);
139 }
140 }
141 };
142 }
143
144
145 public Runnable appendLogProcess(final LogEvent call) {
146 final Runnable appendProcess = new Runnable() {
147 public void run() {
148 String logMessage = "";
149 try {
150 logMessage = getFormatter().formatLogCall(call);
151 fileWriter.write(logMessage);
152
153 fileWriter.flush();
154 } catch (final Exception e) {
155 LogController.getInternalLogger().error(
156 "Could not append message \"{1}\" to file \"{0}\"", e, fileName,
157 logMessage);
158 }
159 }
160
161 };
162 return appendProcess;
163 }
164
165 }