/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/bufferio/BufferLoadRequest.java
Java | 394 lines | 288 code | 29 blank | 77 comment | 34 complexity | d18bbe27f1730cf848c2bbba17e71400 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
1/*
2 * BufferLoadRequest.java - I/O request
3 * :tabSize=8:indentSize=8:noTabs=false:
4 * :folding=explicit:collapseFolds=1:
5 *
6 * Copyright (C) 2000, 2005 Slava Pestov
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23package org.gjt.sp.jedit.bufferio;
24
25//{{{ Imports
26import java.io.*;
27import java.nio.charset.*;
28import java.util.List;
29import java.util.ArrayList;
30import java.util.Set;
31import java.util.HashSet;
32import java.util.zip.GZIPInputStream;
33import org.gjt.sp.jedit.io.*;
34import org.gjt.sp.jedit.*;
35import org.gjt.sp.jedit.buffer.JEditBuffer;
36import org.gjt.sp.util.*;
37//}}}
38
39/**
40 * A buffer load request.
41 * @author Slava Pestov
42 * @version $Id: BufferLoadRequest.java 17734 2010-05-04 22:08:41Z kpouer $
43 */
44public class BufferLoadRequest extends BufferIORequest
45{
46 //{{{ BufferLoadRequest constructor
47 /**
48 * Creates a new buffer I/O request.
49 * @param view The view
50 * @param buffer The buffer
51 * @param session The VFS session
52 * @param vfs The VFS
53 * @param path The path
54 */
55 public BufferLoadRequest(View view, Buffer buffer,
56 Object session, VFS vfs, String path)
57 {
58 super(view,buffer,session,vfs,path);
59 } //}}}
60
61 //{{{ run() method
62 public void run()
63 {
64 try
65 {
66 setAbortable(true);
67 if(!buffer.isTemporary())
68 {
69 String[] args = { vfs.getFileName(path) };
70 setStatus(jEdit.getProperty("vfs.status.load",args));
71 setValue(0L);
72 }
73
74 path = vfs._canonPath(session,path,view);
75
76 readContents();
77 buffer.setNewFile(false);
78
79 if (jEdit.getBooleanProperty("persistentMarkers") &&
80 (vfs.isMarkersFileSupported()))
81 {
82 InputStream markers = null;
83 try
84 {
85 String[] args = { vfs.getFileName(path) };
86 if(!buffer.isTemporary())
87 setStatus(jEdit.getProperty("vfs.status.load-markers",args));
88 setAbortable(true);
89
90 markers = vfs._createInputStream(session,markersPath,true,view);
91 if(markers != null)
92 readMarkers(buffer,markers);
93 }
94 catch(Exception e)
95 {
96 // ignore
97 }
98 finally
99 {
100 IOUtilities.closeQuietly(markers);
101 }
102 }
103 }
104 catch(Exception e)
105 {
106 Log.log(Log.ERROR,this,e);
107 Object[] pp = { e.toString() };
108 VFSManager.error(view,path,"ioerror.read-error",pp);
109
110 buffer.setBooleanProperty(ERROR_OCCURRED,true);
111 }
112 catch(OutOfMemoryError oom)
113 {
114 Log.log(Log.ERROR,this,oom);
115 VFSManager.error(view,path,"out-of-memory-error",null);
116
117 buffer.setBooleanProperty(ERROR_OCCURRED,true);
118 }
119 catch(WorkThread.Abort a)
120 {
121 buffer.setBooleanProperty(ERROR_OCCURRED,true);
122 }
123 finally
124 {
125 try
126 {
127 vfs._endVFSSession(session,view);
128 }
129 catch(Exception e)
130 {
131 Log.log(Log.ERROR,this,e);
132 String[] pp = { e.toString() };
133 VFSManager.error(view,path,"ioerror.read-error",pp);
134
135 buffer.setBooleanProperty(ERROR_OCCURRED,true);
136 }
137 catch(WorkThread.Abort a)
138 {
139 buffer.setBooleanProperty(ERROR_OCCURRED,true);
140 }
141 }
142 } //}}}
143
144 //{{{ getNakedStream() method
145 /**
146 * Returns the raw contents stream for this load request.
147 * This stream is not buffered or unzipped.
148 */
149 private InputStream getNakedStream() throws IOException
150 {
151 InputStream in = vfs._createInputStream(session,path,false,view);
152 if(in != null)
153 {
154 return in;
155 }
156 throw new IOException("Unable to get a Stream for " + path);
157 } //}}}
158
159 //{{{ getContentLength() method
160 /**
161 * Returns content length of this load request.
162 */
163 private long getContentLength() throws IOException
164 {
165 VFSFile entry = vfs._getFile(session,path,view);
166 if(entry != null)
167 return entry.getLength();
168 else
169 return 0L;
170 } //}}}
171
172 //{{{ rewindContentsStream() method
173 /**
174 * Returns rewinded contents stream.
175 * This method assumes the marked stream was made by
176 * getMarkedStream() method. The stream may be reopened if reset()
177 * failed.
178 */
179 private BufferedInputStream rewindContentsStream(BufferedInputStream markedStream, boolean gzipped)
180 throws IOException
181 {
182 try
183 {
184 markedStream.reset();
185 return markedStream;
186 }
187 catch(IOException e)
188 {
189 Log.log(Log.NOTICE, this
190 , path + ": Reopening to rewind the stream");
191 // Reopen the stream because the mark has been
192 // invalidated while previous reading.
193 markedStream.close();
194 InputStream in = getNakedStream();
195 try
196 {
197 if(gzipped)
198 {
199 in = new GZIPInputStream(in);
200 }
201 BufferedInputStream result
202 = AutoDetection.getMarkedStream(in);
203 in = null;
204 return result;
205 }
206 finally
207 {
208 IOUtilities.closeQuietly(in);
209 }
210 }
211 } //}}}
212
213 //{{{ readContents() method
214 /**
215 * Read the contents of this load request.
216 * Some auto detection is performed if enabled.
217 * - GZIPed file
218 * - The encoding
219 * If fallback encodings are specified, they are used on
220 * encoding errors.
221 */
222 private void readContents() throws IOException
223 {
224 long length = getContentLength();
225
226 BufferedInputStream markedStream
227 = AutoDetection.getMarkedStream(getNakedStream());
228 try
229 {
230 boolean gzipped = false;
231 // encodingProviders is consist of given
232 // encodings as String or contents-aware
233 // detectors as EncodingDetector.
234 List<Object> encodingProviders
235 = new ArrayList<Object>();
236
237 boolean autodetect = buffer.getBooleanProperty(Buffer.ENCODING_AUTODETECT);
238 if(autodetect)
239 {
240 gzipped = AutoDetection.isGzipped(markedStream);
241 markedStream.reset();
242
243 encodingProviders.addAll(AutoDetection.getEncodingDetectors());
244 // If the detected encoding fail, fallback to
245 // the original encoding.
246 encodingProviders.add(buffer.getStringProperty(JEditBuffer.ENCODING));
247
248 String fallbackEncodings = jEdit.getProperty("fallbackEncodings");
249 if(fallbackEncodings != null && fallbackEncodings.length() > 0)
250 {
251 for(String encoding: fallbackEncodings.split("\\s+"))
252 {
253 encodingProviders.add(encoding);
254 }
255 }
256 }
257 else
258 {
259 gzipped = buffer.getBooleanProperty(Buffer.GZIPPED);
260 encodingProviders.add(buffer.getStringProperty(JEditBuffer.ENCODING));
261 }
262
263 if(gzipped)
264 {
265 Log.log(Log.DEBUG, this, path + ": Stream is gzipped.");
266 markedStream = AutoDetection.getMarkedStream(
267 new GZIPInputStream(markedStream));
268 }
269
270 Set<String> failedEncodings = new HashSet<String>();
271 Exception encodingError = null;
272 for(Object encodingProvider: encodingProviders)
273 {
274 String encoding = null;
275 if (encodingProvider instanceof String)
276 {
277 encoding = (String)encodingProvider;
278 }
279 else if(encodingProvider instanceof EncodingDetector)
280 {
281 markedStream = rewindContentsStream(markedStream, gzipped);
282 encoding = ((EncodingDetector)encodingProvider).detectEncoding(new BufferedInputStream(markedStream));
283 }
284 else
285 {
286 Log.log(Log.DEBUG, this, "Strange encodingProvider: " + encodingProvider);
287 }
288
289 if(encoding == null || encoding.length() <= 0
290 || failedEncodings.contains(encoding))
291 {
292 continue;
293 }
294
295 markedStream = rewindContentsStream(markedStream, gzipped);
296 try
297 {
298 read(EncodingServer.getTextReader(markedStream, encoding)
299 , length, false);
300 if(autodetect)
301 {
302 // Store the successful properties.
303 if(gzipped)
304 {
305 buffer.setBooleanProperty(Buffer.GZIPPED,true);
306 }
307 buffer.setProperty(JEditBuffer.ENCODING, encoding);
308 }
309 return;
310 }
311 catch(CharConversionException e)
312 {
313 encodingError = e;
314 }
315 catch(CharacterCodingException e)
316 {
317 encodingError = e;
318 }
319 catch(UnsupportedEncodingException e)
320 {
321 encodingError = e;
322 }
323 catch(UnsupportedCharsetException e)
324 {
325 encodingError = e;
326 }
327 Log.log(Log.NOTICE, this, path + ": " + encoding
328 + ": " + encodingError);
329 failedEncodings.add(encoding);
330 }
331 // All possible detectors and encodings failed.
332 Object[] pp = { TextUtilities.join(failedEncodings,","), "" };
333 if(failedEncodings.size() < 2)
334 {
335 pp[1] = encodingError.toString();
336 }
337 else
338 {
339 pp[1] = "See details in Activity Log";
340 }
341 VFSManager.error(view,path,"ioerror.encoding-error",pp);
342 markedStream = rewindContentsStream(markedStream, gzipped);
343 read(EncodingServer.getEncoding(
344 buffer.getStringProperty(JEditBuffer.ENCODING)
345 ).getPermissiveTextReader(markedStream)
346 , length, false);
347 if(autodetect && gzipped)
348 {
349 buffer.setBooleanProperty(Buffer.GZIPPED,true);
350 }
351 }
352 finally
353 {
354 markedStream.close();
355 }
356 } //}}}
357
358 //{{{ readMarkers() method
359 private static void readMarkers(Buffer buffer, InputStream _in)
360 throws IOException
361 {
362 // For `reload' command
363 buffer.removeAllMarkers();
364
365 BufferedReader in = new BufferedReader(new InputStreamReader(_in));
366
367 try
368 {
369 String line;
370 while((line = in.readLine()) != null)
371 {
372 // malformed marks file?
373 if(line.length() == 0)
374 continue;
375
376 // compatibility kludge for jEdit 3.1 and earlier
377 if(line.charAt(0) != '!')
378 continue;
379
380
381 char shortcut = line.charAt(1);
382 int start = line.indexOf(';');
383 int end = line.indexOf(';',start + 1);
384 int position = Integer.parseInt(line.substring(start + 1,end));
385 buffer.addMarker(shortcut,position);
386 }
387 buffer.setMarkersChanged(false);
388 }
389 finally
390 {
391 in.close();
392 }
393 } //}}}
394}