PageRenderTime 44ms CodeModel.GetById 23ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/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}