1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package net.grinder.console.editor;
23
24 import java.io.BufferedReader;
25 import java.io.File;
26 import java.io.FileNotFoundException;
27 import java.io.FileReader;
28 import java.io.FileWriter;
29 import java.io.IOException;
30 import java.io.PrintWriter;
31 import java.io.StringWriter;
32 import java.io.Writer;
33 import java.util.EventListener;
34
35 import net.grinder.common.Closer;
36 import net.grinder.common.UncheckedInterruptedException;
37 import net.grinder.console.common.DisplayMessageConsoleException;
38 import net.grinder.console.common.Resources;
39 import net.grinder.util.ListenerSupport;
40
41
42
43
44
45
46
47 final class BufferImplementation implements Buffer {
48
49 private final Resources m_resources;
50 private final TextSource m_textSource;
51
52 private final ListenerSupport<Listener> m_listeners =
53 new ListenerSupport<Listener>();
54
55 private String m_name;
56 private File m_file;
57
58 private long m_lastModified = -1;
59
60
61
62
63
64
65
66 BufferImplementation(Resources resources,
67 TextSource textSource,
68 String name) {
69 m_resources = resources;
70 m_textSource = textSource;
71 m_file = null;
72 m_name = name;
73 }
74
75
76
77
78
79
80
81
82 BufferImplementation(Resources resources, TextSource textSource, File file) {
83 m_resources = resources;
84 m_textSource = textSource;
85 setFile(file);
86 }
87
88
89
90
91
92
93 public TextSource getTextSource() {
94 return m_textSource;
95 }
96
97
98
99
100
101
102
103
104 public void load() throws DisplayMessageConsoleException, EditorException {
105
106
107 if (m_file == null) {
108 throw new EditorException(
109 "Can't load a buffer that has no associated file");
110 }
111
112 final StringWriter stringWriter = new StringWriter();
113 BufferedReader reader = null;
114
115 try {
116
117 reader = new BufferedReader(new FileReader(m_file));
118
119 while (true) {
120 final String line = reader.readLine();
121
122 if (line == null) {
123 break;
124 }
125
126 stringWriter.write(line);
127 stringWriter.write('\n');
128 }
129 }
130 catch (IOException e) {
131 UncheckedInterruptedException.ioException(e);
132
133 throw new DisplayMessageConsoleException(
134 m_resources,
135 "fileReadError.text",
136 new Object[] { m_file,
137 ".\n(" + extractReasonFromIOException(e) + ")",
138 },
139 e);
140 }
141 finally {
142 Closer.close(reader);
143 }
144
145 m_textSource.setText(stringWriter.toString());
146
147 m_lastModified = m_file.lastModified();
148 }
149
150
151
152
153
154
155
156
157 public void save() throws DisplayMessageConsoleException, EditorException {
158
159
160 if (m_file == null) {
161 throw new EditorException(
162 "Can't save a buffer that has no associated file");
163 }
164
165 save(m_file);
166 }
167
168
169
170
171
172
173
174
175
176 public void save(File file) throws DisplayMessageConsoleException {
177 final File oldFile = getFile();
178
179 Writer fileWriter = null;
180
181 try {
182
183
184 final String text = m_textSource.getText();
185
186
187
188
189 final String[] lines = text.split("\n", -1);
190
191 fileWriter = new FileWriter(file);
192 final PrintWriter printWriter = new PrintWriter(fileWriter);
193
194 for (int i = 0; i < lines.length; ++i) {
195 printWriter.println(lines[i]);
196 }
197
198 setFile(file);
199 printWriter.close();
200
201 m_lastModified = m_file.lastModified();
202
203 m_listeners.apply(
204 new ListenerSupport.Informer<Listener>() {
205 public void inform(Listener l) {
206 l.bufferSaved(BufferImplementation.this, oldFile);
207 }
208 });
209 }
210 catch (IOException e) {
211 UncheckedInterruptedException.ioException(e);
212
213 throw new DisplayMessageConsoleException(
214 m_resources,
215 "fileWriteError.text",
216 new Object[] { m_file,
217 "./n(" + extractReasonFromIOException(e) + ")",
218 },
219 e);
220 }
221 finally {
222 Closer.close(fileWriter);
223 }
224 }
225
226
227
228
229
230
231
232 public boolean isDirty() {
233 return m_textSource.isDirty();
234 }
235
236 private void setFile(File file) {
237 m_file = file;
238 m_name = file.getName();
239 }
240
241
242
243
244
245
246 public File getFile() {
247 return m_file;
248 }
249
250
251
252
253
254
255
256
257 public boolean isUpToDate() {
258 return m_file == null || m_lastModified == m_file.lastModified();
259 }
260
261
262
263
264
265
266 public Type getType() {
267
268 if (m_file != null) {
269 final String name = m_file.getName();
270 final int lastDot = name.lastIndexOf('.');
271
272 if (lastDot >= 0) {
273 final String extension = name.substring(lastDot + 1);
274 return Type.forExtension(extension);
275 }
276 }
277
278 return Type.TEXT_BUFFER;
279 }
280
281
282
283
284
285
286 public String getDisplayName() {
287 return m_name;
288 }
289
290
291
292
293
294
295 @Override public String toString() {
296 return "<Buffer " + hashCode() + " '" + getDisplayName() + "'>";
297 }
298
299
300
301
302
303
304 public void addListener(Listener listener) {
305 m_listeners.add(listener);
306 }
307
308
309
310
311 public interface Listener extends EventListener {
312
313
314
315
316
317
318
319 void bufferSaved(Buffer buffer, File oldFile);
320 }
321
322
323
324
325 static String extractReasonFromIOException(IOException e) {
326 if (e instanceof FileNotFoundException) {
327 final String message = e.getMessage();
328
329 final int firstParenthesis = message.indexOf('(');
330 final int secondsParenthesis = message.indexOf(')', firstParenthesis);
331
332 if (firstParenthesis >= 0 && secondsParenthesis > firstParenthesis + 1) {
333 return message.substring(firstParenthesis + 1, secondsParenthesis);
334 }
335 }
336
337 return "";
338 }
339 }