📄 vfs.java
字号:
/* * VFS.java - Virtual filesystem implementation * :tabSize=8:indentSize=8:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 2000, 2002 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.io;//{{{ Importsimport gnu.regexp.*;import java.awt.Color;import java.awt.Component;import java.io.*;import java.util.*;import org.gjt.sp.jedit.buffer.BufferIORequest;import org.gjt.sp.jedit.msg.PropertiesChanged;import org.gjt.sp.jedit.*;import org.gjt.sp.util.Log;//}}}/** * A virtual filesystem implementation.<p> * * <b>Session objects:</b><p> * * A session is used to persist things like login information, any network * sockets, etc. File system implementations that do not need this kind of * persistence return a dummy object as a session.<p> * * Methods whose names are prefixed with "_" expect to be given a * previously-obtained session object. A session must be obtained from the AWT * thread in one of two ways: * * <ul> * <li>{@link #createVFSSession(String,Component)}</li> * <li>{@link #showBrowseDialog(Object[],Component)}</li> * </ul> * * When done, the session must be disposed of using * {@link #_endVFSSession(Object,Component)}.<p> * * <b>Thread safety:</b><p> * * The following methods cannot be called from an I/O thread: * * <ul> * <li>{@link #createVFSSession(String,Component)}</li> * <li>{@link #insert(View,Buffer,String)}</li> * <li>{@link #load(View,Buffer,String)}</li> * <li>{@link #save(View,Buffer,String)}</li> * <li>{@link #showBrowseDialog(Object[],Component)}</li> * </ul> * * All remaining methods are (required to be) thread-safe. * * @see VFSManager#registerVFS(String,VFS) * @see VFSManager#getVFSByName(String) * @see VFSManager#getVFSForPath(String) * @see VFSManager#getVFSForProtocol(String) * * @author Slava Pestov * @author $Id: VFS.java,v 1.25 2003/02/11 02:31:06 spestov Exp $ */public abstract class VFS{ //{{{ Capabilities /** * Read capability. * @since jEdit 2.6pre2 */ public static final int READ_CAP = 1 << 0; /** * Write capability. * @since jEdit 2.6pre2 */ public static final int WRITE_CAP = 1 << 1; /** * If set, a menu item for this VFS will appear in the browser's * <b>Plugins</b> menu. The property <code>vfs.<i>name</i>.label</code> * is used as a menu item label.<p> * * When invoked, the menu item calls the * {@link #showBrowseDialog(Object[],Component)} method of the VFS, * and then lists the directory returned by that method.<p> * * If this capability is not set, it will still be possible to type in * URLs for this VFS in the browser, but there won't be a user-visible * way of doing this. * * @since jEdit 2.6pre2 */ public static final int BROWSE_CAP = 1 << 2; /** * Delete file capability. * @since jEdit 2.6pre2 */ public static final int DELETE_CAP = 1 << 3; /** * Rename file capability. * @since jEdit 2.6pre2 */ public static final int RENAME_CAP = 1 << 4; /** * Make directory capability. * @since jEdit 2.6pre2 */ public static final int MKDIR_CAP = 1 << 5; /** * Low latency capability. If this is not set, then a confirm dialog * will be shown before doing a directory search in this VFS. * @since jEdit 4.1pre1 */ public static final int LOW_LATENCY_CAP = 1 << 6; //}}} //{{{ VFS constructor /** * Creates a new virtual filesystem. * @param name The name */ public VFS(String name) { this.name = name; } //}}} //{{{ VFS constructor /** * Creates a new virtual filesystem. * @param name The name * @param caps The capabilities */ public VFS(String name, int caps) { this.name = name; this.caps = caps; } //}}} //{{{ getName() method /** * Returns this VFS's name. The name is used to obtain the * label stored in the <code>vfs.<i>name</i>.label</code> * property. */ public String getName() { return name; } //}}} //{{{ getCapabilities() method /** * Returns the capabilities of this VFS. * @since jEdit 2.6pre2 */ public int getCapabilities() { return caps; } //}}} //{{{ showBrowseDialog() method /** * Displays a dialog box that should set up a session and return * the initial URL to browse. * @param session Where the VFS session will be stored * @param comp The component that will parent error dialog boxes * @return The URL * @since jEdit 2.7pre1 */ public String showBrowseDialog(Object[] session, Component comp) { return null; } //}}} //{{{ getFileName() method /** * Returns the file name component of the specified path. * @param path The path * @since jEdit 3.1pre4 */ public String getFileName(String path) { if(path.equals("/")) return path; int count = Math.max(0,path.length() - 2); int index = Math.max(path.lastIndexOf('/',count), path.lastIndexOf(File.separatorChar,count)); if(index == -1) index = path.indexOf(':'); // don't want getFileName("roots:") to return "" if(index == -1 || index == path.length() - 1) return path; return path.substring(index + 1); } //}}} //{{{ getParentOfPath() method /** * Returns the parent of the specified path. This must be * overridden to return a non-null value for browsing of this * filesystem to work. * @param path The path * @since jEdit 2.6pre5 */ public String getParentOfPath(String path) { // ignore last character of path to properly handle // paths like /foo/bar/ int count = Math.max(0,path.length() - 2); int index = path.lastIndexOf(File.separatorChar,count); if(index == -1) index = path.lastIndexOf('/',count); if(index == -1) { // this ensures that getFileParent("protocol:"), for // example, is "protocol:" and not "". index = path.lastIndexOf(':'); } return path.substring(0,index + 1); } //}}} //{{{ constructPath() method /** * Constructs a path from the specified directory and * file name component. This must be overridden to return a * non-null value, otherwise browsing this filesystem will * not work.<p> * * Unless you are writing a VFS, this method should not be called * directly. To ensure correct behavior, you <b>must</b> call * {@link org.gjt.sp.jedit.MiscUtilities#constructPath(String,String)} * instead. * * @param parent The parent directory * @param path The path * @since jEdit 2.6pre2 */ public String constructPath(String parent, String path) { return parent + path; } //}}} //{{{ getFileSeparator() method /** * Returns the file separator used by this VFS. * @since jEdit 2.6pre9 */ public char getFileSeparator() { return '/'; } //}}} //{{{ getTwoStageSaveName() method /** * Returns a temporary file name based on the given path. * * By default jEdit first saves a file to <code>#<i>name</i>#save#</code> * and then renames it to the original file. However some virtual file * systems might not support the <code>#</code> character in filenames, * so this method permits the VFS to override this behavior. * * @param path The path name * @since jEdit 4.1pre7 */ public String getTwoStageSaveName(String path) { return MiscUtilities.constructPath(getParentOfPath(path), '#' + getFileName(path) + "#save#"); } //}}} //{{{ reloadDirectory() method /** * Called before a directory is reloaded by the file system browser. * Can be used to flush a cache, etc. * @since jEdit 4.0pre3 */ public void reloadDirectory(String path) {} //}}} //{{{ createVFSSession() method /** * Creates a VFS session. This method is called from the AWT thread, * so it should not do any I/O. It could, however, prompt for * a login name and password, for example. * @param path The path in question * @param comp The component that will parent any dialog boxes shown * @return The session * @since jEdit 2.6pre3 */ public Object createVFSSession(String path, Component comp) { return new Object(); } //}}} //{{{ load() method /** * Loads the specified buffer. The default implementation posts * an I/O request to the I/O thread. * @param view The view * @param buffer The buffer * @param path The path */ public boolean load(View view, Buffer buffer, String path) { if((getCapabilities() & READ_CAP) == 0) { VFSManager.error(view,path,"vfs.not-supported.load",new String[] { name }); return false; } Object session = createVFSSession(path,view); if(session == null) return false; if((getCapabilities() & WRITE_CAP) == 0) buffer.setReadOnly(true); BufferIORequest request = new BufferIORequest( BufferIORequest.LOAD,view,buffer,session,this,path); if(buffer.isTemporary()) // this makes HyperSearch much faster request.run(); else VFSManager.runInWorkThread(request); return true; } //}}} //{{{ save() method /** * Saves the specifies buffer. The default implementation posts * an I/O request to the I/O thread. * @param view The view * @param buffer The buffer * @param path The path */ public boolean save(View view, Buffer buffer, String path) { if((getCapabilities() & WRITE_CAP) == 0) { VFSManager.error(view,path,"vfs.not-supported.save",new String[] { name }); return false; } Object session = createVFSSession(path,view); if(session == null) return false; /* When doing a 'save as', the path to save to (path) * will not be the same as the buffer's previous path * (buffer.getPath()). In that case, we want to create * a backup of the new path, even if the old path was * backed up as well (BACKED_UP property set) */ if(!path.equals(buffer.getPath())) buffer.unsetProperty(Buffer.BACKED_UP); VFSManager.runInWorkThread(new BufferIORequest( BufferIORequest.SAVE,view,buffer,session,this,path)); return true; } //}}} //{{{ insert() method /** * Inserts a file into the specified buffer. The default implementation * posts an I/O request to the I/O thread. * @param view The view * @param buffer The buffer * @param path The path */ public boolean insert(View view, Buffer buffer, String path) { if((getCapabilities() & READ_CAP) == 0) { VFSManager.error(view,path,"vfs.not-supported.load",new String[] { name }); return false; } Object session = createVFSSession(path,view); if(session == null) return false; VFSManager.runInWorkThread(new BufferIORequest( BufferIORequest.INSERT,view,buffer,session,this,path)); return true; } //}}} // the remaining methods are called from the I/O thread //{{{ _canonPath() method /** * Returns the canonical form of the specified path name. For example, * <code>~</code> might be expanded to the user's home directory. * @param session The session * @param path The path * @param comp The component that will parent error dialog boxes * @exception IOException if an I/O error occurred * @since jEdit 4.0pre2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -