/* * BufferLoadRequest.java - I/O request * :tabSize=4:indentSize=4:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 2000, 2005 Slava Pestov * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gjt.sp.jedit.bufferio; //{{{ Imports import java.io.*; import java.nio.charset.*; import java.util.Collections; import java.util.List; import java.util.ArrayList; import java.util.Set; import java.util.HashSet; import java.util.zip.GZIPInputStream; import org.gjt.sp.jedit.io.*; import org.gjt.sp.jedit.*; import org.gjt.sp.jedit.buffer.JEditBuffer; import org.gjt.sp.util.*; //}}} /** * A buffer load request. * @author Slava Pestov * @version $Id: BufferLoadRequest.java 23224 2013-09-30 20:51:42Z shlomy $ */ public class BufferLoadRequest extends BufferIORequest { //{{{ BufferLoadRequest constructor /** * Creates a new buffer I/O request. * @param view The view * @param buffer The buffer * @param session The VFS session * @param vfs The VFS * @param path The path */ public BufferLoadRequest(View view, Buffer buffer, Object session, VFS vfs, String path) { super(view,buffer,session,vfs,path); } //}}} //{{{ run() method public void _run() { try { setCancellable(true); if(!buffer.isTemporary()) { String[] args = { vfs.getFileName(path) }; setStatus(jEdit.getProperty("vfs.status.load",args)); setValue(0L); } path = vfs._canonPath(session,path,view); readContents(); buffer.setNewFile(false); if (jEdit.getBooleanProperty("persistentMarkers") && (vfs.isMarkersFileSupported())) { InputStream markers = null; try { String[] args = { vfs.getFileName(path) }; if(!buffer.isTemporary()) setStatus(jEdit.getProperty("vfs.status.load-markers",args)); setCancellable(true); markers = vfs._createInputStream(session,markersPath,true,view); if(markers != null) readMarkers(buffer,markers); } catch(Exception e) { // ignore } finally { IOUtilities.closeQuietly(markers); } } } catch(InterruptedException e) { buffer.setBooleanProperty(ERROR_OCCURRED,true); Thread.currentThread().interrupt(); } catch(Exception e) { Log.log(Log.ERROR,this,e); Object[] pp = { e.toString() }; VFSManager.error(view,path,"ioerror.read-error",pp); buffer.setBooleanProperty(ERROR_OCCURRED,true); } catch(OutOfMemoryError oom) { Log.log(Log.ERROR,this,oom); VFSManager.error(view,path,"out-of-memory-error",null); buffer.setBooleanProperty(ERROR_OCCURRED,true); } finally { try { vfs._endVFSSession(session,view); } catch(Exception e) { Log.log(Log.ERROR,this,e); String[] pp = { e.toString() }; VFSManager.error(view,path,"ioerror.read-error",pp); buffer.setBooleanProperty(ERROR_OCCURRED,true); } } } //}}} //{{{ getNakedStream() method /** * Returns the raw contents stream for this load request. * This stream is not buffered or unzipped. */ private InputStream getNakedStream() throws IOException { InputStream in = vfs._createInputStream(session,path,false,view); if(in != null) { return in; } throw new IOException("Unable to get a Stream for " + path); } //}}} //{{{ getContentLength() method /** * Returns content length of this load request. */ private long getContentLength() throws IOException { VFSFile entry = vfs._getFile(session,path,view); if(entry != null) return entry.getLength(); else return 0L; } //}}} //{{{ rewindContentsStream() method /** * Returns rewinded contents stream. * This method assumes the marked stream was made by * getMarkedStream() method. The stream may be reopened if reset() * failed. */ private BufferedInputStream rewindContentsStream(BufferedInputStream markedStream, boolean gzipped) throws IOException { try { markedStream.reset(); return markedStream; } catch(IOException e) { Log.log(Log.NOTICE, this , path + ": Reopening to rewind the stream"); // Reopen the stream because the mark has been // invalidated while previous reading. markedStream.close(); InputStream in = getNakedStream(); try { if(gzipped) { in = new GZIPInputStream(in); } BufferedInputStream result = AutoDetection.getMarkedStream(in); in = null; return result; } finally { IOUtilities.closeQuietly((Closeable)in); } } } //}}} //{{{ readContents() method /** * Read the contents of this load request. * Some auto detection is performed if enabled. * - GZIPed file * - The encoding * If fallback encodings are specified, they are used on * encoding errors. * @throws InterruptedException */ private void readContents() throws IOException, InterruptedException { long length = getContentLength(); BufferedInputStream markedStream = AutoDetection.getMarkedStream(getNakedStream()); try { boolean gzipped = false; // encodingProviders is consist of given // encodings as String or contents-aware // detectors as EncodingDetector. List<Object> encodingProviders = new ArrayList<Object>(); boolean autodetect = buffer.getBooleanProperty(Buffer.ENCODING_AUTODETECT); if(autodetect) { gzipped = AutoDetection.isGzipped(markedStream); markedStream.reset(); encodingProviders.addAll(AutoDetection.getEncodingDetectors()); // If the detected encoding fail, fallback to // the original encoding. encodingProviders.add(buffer.getStringProperty(JEditBuffer.ENCODING)); String fallbackEncodings = jEdit.getProperty("fallbackEncodings"); if(fallbackEncodings != null && fallbackEncodings.length() > 0) Collections.addAll(encodingProviders, fallbackEncodings.split("\\s+")); } else { gzipped = buffer.getBooleanProperty(Buffer.GZIPPED); encodingProviders.add(buffer.getStringProperty(JEditBuffer.ENCODING)); } if(gzipped) { Log.log(Log.DEBUG, this, path + ": Stream is gzipped."); markedStream = AutoDetection.getMarkedStream( new GZIPInputStream(markedStream)); } Set<String> failedEncodings = new HashSet<String>(); Exception encodingError = null; for(Object encodingProvider: encodingProviders) { String encoding = null; if (encodingProvider instanceof String) { encoding = (String)encodingProvider; } else if(encodingProvider instanceof EncodingDetector) { markedStream = rewindContentsStream(markedStream, gzipped); encoding = ((EncodingDetector)encodingProvider).detectEncoding(new BufferedInputStream(markedStream)); } else { Log.log(Log.DEBUG, this, "Strange encodingProvider: " + encodingProvider); } if(encoding == null || encoding.length() <= 0 || failedEncodings.contains(encoding)) { continue; } markedStream = rewindContentsStream(markedStream, gzipped); try { read(EncodingServer.getTextReader(markedStream, encoding) , length, false); if(autodetect) { // Store the successful properties. if(gzipped) { buffer.setBooleanProperty(Buffer.GZIPPED,true); } buffer.setProperty(JEditBuffer.ENCODING, encoding); } return; } catch(CharConversionException e) { encodingError = e; } catch(CharacterCodingException e) { encodingError = e; } catch(UnsupportedEncodingException e) { encodingError = e; } catch(UnsupportedCharsetException e) { encodingError = e; } Log.log(Log.NOTICE, this, path + ": " + encoding + ": " + encodingError); failedEncodings.add(encoding); } // All possible detectors and encodings failed. Object[] pp = { TextUtilities.join(failedEncodings,","), "" }; if(failedEncodings.size() < 2) { pp[1] = encodingError.toString(); } else { pp[1] = "See details in Activity Log"; } VFSManager.error(view,path,"ioerror.encoding-error",pp,Log.NOTICE); markedStream = rewindContentsStream(markedStream, gzipped); read(EncodingServer.getEncoding( buffer.getStringProperty(JEditBuffer.ENCODING) ).getPermissiveTextReader(markedStream) , length, false); if(autodetect && gzipped) { buffer.setBooleanProperty(Buffer.GZIPPED,true); } } finally { markedStream.close(); } } //}}} //{{{ readMarkers() method private static void readMarkers(Buffer buffer, InputStream _in) throws IOException, InterruptedException { // For `reload' command buffer.removeAllMarkers(); BufferedReader in = new BufferedReader(new InputStreamReader(_in)); try { String line; while((line = in.readLine()) != null) { if(Thread.interrupted()) throw new InterruptedException(); // malformed marks file? if(line.length() == 0) continue; // compatibility kludge for jEdit 3.1 and earlier if(line.charAt(0) != '!') continue; char shortcut = line.charAt(1); int start = line.indexOf(';'); int end = line.indexOf(';',start + 1); int position = Integer.parseInt(line.substring(start + 1,end)); buffer.addMarker(shortcut,position); } buffer.setMarkersChanged(false); } finally { in.close(); } } //}}} }