All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gjt.sp.jedit.io.FileVFS Maven / Gradle / Ivy

/*
 * FileVFS.java - Local filesystem VFS
 * :tabSize=8:indentSize=8:noTabs=false:
 * :folding=explicit:collapseFolds=1:
 *
 * Copyright (C) 1998, 2005 Slava Pestov
 * Portions copyright (C) 1998, 1999, 2000 Peter Graves
 * Portions copyright (C) 2007 Matthieu Casanova
 *
 * 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;

//{{{ Imports
import javax.swing.filechooser.FileSystemView;
import javax.swing.*;
import java.awt.Component;
import java.io.*;
import java.text.*;
import java.util.Date;
import org.gjt.sp.jedit.*;
import org.gjt.sp.util.Log;
//}}}

/**
 * Local filesystem VFS.
 * @author Slava Pestov
 * @version $Id: FileVFS.java 12504 2008-04-22 23:12:43Z ezust $
 */
public class FileVFS extends VFS
{
	public static final String PERMISSIONS_PROPERTY = "FileVFS__perms";

	//{{{ FileVFS constructor
	public FileVFS()
	{
		super("file",READ_CAP | WRITE_CAP | BROWSE_CAP | DELETE_CAP
			| RENAME_CAP | MKDIR_CAP | LOW_LATENCY_CAP
			| ((OperatingSystem.isCaseInsensitiveFS())
			? CASE_INSENSITIVE_CAP : 0),
			new String[] { EA_TYPE, EA_SIZE, EA_STATUS,
			EA_MODIFIED });
	} //}}}

	//{{{ getParentOfPath() method
	public String getParentOfPath(String path)
	{
		if(OperatingSystem.isDOSDerived())
		{
			if(path.length() == 2 && path.charAt(1) == ':')
				return FileRootsVFS.PROTOCOL + ':';
			else if(path.length() == 3 && path.endsWith(":\\"))
				return FileRootsVFS.PROTOCOL + ':';
			else if(path.startsWith("\\\\") && path.indexOf('\\',2) == -1)
				return path;
		}

		return super.getParentOfPath(path);
	} //}}}

	//{{{ constructPath() method
	public String constructPath(String parent, String path)
	{
		if(parent.endsWith(File.separator)
			|| parent.endsWith("/"))
			return parent + path;
		else
			return parent + File.separator + path;
	} //}}}

	//{{{ getFileSeparator() method
	public char getFileSeparator()
	{
		return File.separatorChar;
	} //}}}

	//{{{ getTwoStageSaveName() method
	/**
	 * Returns a temporary file name based on the given path.
	 *
	 * 

If the directory where the file would be created cannot be * written (i.e., no new files can be created in that directory), * this method returns null.

* * @param path The path name */ public String getTwoStageSaveName(String path) { File parent = new File(getParentOfPath(path)); // the ignorance of the canWrite() method for windows // is, because the read-only flag on windows has // not the effect of preventing the creation of new files. // The only way to make a directory read-only in this means // the ACL of the directory has to be set to read-only, // which is not checkable by java. // The " || OperatingSystem.isWindows()" can be removed // if the canWrite() method gives back the right value. return (parent.canWrite() || OperatingSystem.isWindows()) ? super.getTwoStageSaveName(path) : null; } //}}} //{{{ save() method public boolean save(View view, Buffer buffer, String path) { if(OperatingSystem.isUnix()) { int permissions = getPermissions(buffer.getPath()); Log.log(Log.DEBUG,this,buffer.getPath() + " has permissions 0" + Integer.toString(permissions,8)); buffer.setIntegerProperty(PERMISSIONS_PROPERTY,permissions); } return super.save(view,buffer,path); } //}}} //{{{ insert() method public boolean insert(View view, Buffer buffer, String path) { File file = new File(path); //{{{ Check if file is valid if(!file.exists()) return false; if(file.isDirectory()) { VFSManager.error(view,file.getPath(), "ioerror.open-directory",null); return false; } if(!file.canRead()) { VFSManager.error(view,file.getPath(), "ioerror.no-read",null); return false; } //}}} return super.insert(view,buffer,path); } //}}} //{{{ recursiveDelete() method /** * # * @param path the directory path to recursive delete * @return true if successful, else false */ public static boolean recursiveDelete(File path) { if( path.exists() ) { File[] files = path.listFiles(); for(int i=0; i~
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 */ public String _canonPath(Object session, String path, Component comp) throws IOException { return MiscUtilities.canonPath(path); } //}}} //{{{ LocalFile class public static class LocalFile extends VFSFile { private File file; // use system default short format public static DateFormat DATE_FORMAT = DateFormat.getInstance(); /** * @deprecated Call getModified() instead. */ public long modified; //{{{ LocalFile() class public LocalFile(File file) { this.file = file; /* These attributes are fetched relatively quickly. The rest are lazily filled in. */ setName(file.getName()); String path = file.getPath(); setPath(path); setDeletePath(path); setHidden(file.isHidden()); setType(file.isDirectory() ? VFSFile.DIRECTORY : VFSFile.FILE); } //}}} //{{{ getExtendedAttribute() method public String getExtendedAttribute(String name) { fetchAttrs(); if (name.equals(EA_MODIFIED)) { return DATE_FORMAT.format(new Date(modified)); } else { return super.getExtendedAttribute(name); } } //}}} //{{{ fetchAttrs() method /** Fetch the attributes of the local file. */ protected void fetchAttrs() { if(fetchedAttrs()) return; super.fetchAttrs(); setSymlinkPath(MiscUtilities.resolveSymlinks( file.getPath())); setReadable(file.canRead()); setWriteable(file.canWrite()); setLength(file.length()); setModified(file.lastModified()); } //}}} //{{{ getIcon() method /** * Returns the file system icon for the file. * * @param expanded not used here * @param openBuffer not used here * @return the file system icon * @since 4.3pre9 */ public Icon getIcon(boolean expanded, boolean openBuffer) { if (icon == null) { if (fsView == null) fsView = FileSystemView.getFileSystemView(); icon = fsView.getSystemIcon(file); } return icon; } //}}} //{{{ getSymlinkPath() method public String getSymlinkPath() { fetchAttrs(); return super.getSymlinkPath(); } //}}} //{{{ getLength() method public long getLength() { fetchAttrs(); return super.getLength(); } //}}} //{{{ isReadable() method public boolean isReadable() { fetchAttrs(); return super.isReadable(); } //}}} //{{{ isWriteable() method public boolean isWriteable() { fetchAttrs(); return super.isWriteable(); } //}}} //{{{ getModified() method public long getModified() { fetchAttrs(); return modified; } //}}} //{{{ setModified() method public void setModified(long modified) { this.modified = modified; } //}}} private transient FileSystemView fsView; private transient Icon icon; } //}}} //{{{ _listFiles() method public VFSFile[] _listFiles(Object session, String path, Component comp) { //{{{ Windows work around /* On Windows, paths of the form X: list the last *working * directory* on that drive. To list the root of the drive, * you must use X:\. * * However, the VFS browser and friends strip off trailing * path separators, for various reasons. So to work around * that, we add a '\' to drive letter paths on Windows. */ if(OperatingSystem.isWindows()) { if(path.length() == 2 && path.charAt(1) == ':') path = path.concat(File.separator); } //}}} File directory = new File(path); File[] list = null; if(directory.exists()) list = fsView.getFiles(directory,false); if(list == null) { VFSManager.error(comp,path,"ioerror.directory-error-nomsg",null); return null; } VFSFile[] list2 = new VFSFile[list.length]; for(int i = 0; i < list.length; i++) list2[i] = new LocalFile(list[i]); return list2; } //}}} //{{{ _getFile() method public VFSFile _getFile(Object session, String path, Component comp) { if(path.equals("/") && OperatingSystem.isUnix()) { return new VFS.DirectoryEntry(path,path,path, VFSFile.DIRECTORY,0L,false); } File file = new File(path); if(!file.exists()) return null; return new LocalFile(file); } //}}} //{{{ _delete() method public boolean _delete(Object session, String path, Component comp) { File file = new File(path); // do some platforms throw exceptions if the file does not exist // when we ask for the canonical path? String canonPath; try { canonPath = file.getCanonicalPath(); } catch(IOException io) { canonPath = path; } // if directory, do recursive delete boolean retVal; if (!file.isDirectory()) { retVal = file.delete(); } else { retVal = recursiveDelete(file); } if(retVal) VFSManager.sendVFSUpdate(this,canonPath,true); return retVal; } //}}} //{{{ _rename() method public boolean _rename(Object session, String from, String to, Component comp) { File _to = new File(to); String toCanonPath; try { toCanonPath = _to.getCanonicalPath(); } catch(IOException io) { toCanonPath = to; } // this is needed because on OS X renaming to a non-existent // directory causes problems File parent = new File(_to.getParent()); if(parent.exists()) { if(!parent.isDirectory()) return false; } else { parent.mkdirs(); if(!parent.exists()) return false; } File _from = new File(from); String fromCanonPath; try { fromCanonPath = _from.getCanonicalPath(); } catch(IOException io) { fromCanonPath = from; } // Case-insensitive fs workaround if(!fromCanonPath.equalsIgnoreCase(toCanonPath)) _to.delete(); boolean retVal = _from.renameTo(_to); VFSManager.sendVFSUpdate(this,fromCanonPath,true); VFSManager.sendVFSUpdate(this,toCanonPath,true); return retVal; } //}}} //{{{ _mkdir() method public boolean _mkdir(Object session, String directory, Component comp) { String parent = getParentOfPath(directory); if(!new File(parent).exists()) { if(!_mkdir(session,parent,comp)) return false; } File file = new File(directory); boolean retVal = file.mkdir(); String canonPath; try { canonPath = file.getCanonicalPath(); } catch(IOException io) { canonPath = directory; } VFSManager.sendVFSUpdate(this,canonPath,true); return retVal; } //}}} //{{{ _backup() method public void _backup(Object session, String path, Component comp) throws IOException { // Fetch properties int backups = jEdit.getIntegerProperty("backups",1); if(backups == 0) return; String backupPrefix = jEdit.getProperty("backup.prefix"); String backupSuffix = jEdit.getProperty("backup.suffix"); String backupDirectory = jEdit.getProperty("backup.directory"); int backupTimeDistance = jEdit.getIntegerProperty("backup.minTime",0); File file = new File(path); if (!file.exists()) return; // Check for backup.directory, and create that // directory if it doesn't exist if(backupDirectory == null || backupDirectory.length() == 0) backupDirectory = file.getParent(); else { backupDirectory = MiscUtilities.constructPath( System.getProperty("user.home"),backupDirectory); // Perhaps here we would want to guard with // a property for parallel backups or not. backupDirectory = MiscUtilities.concatPath( backupDirectory,file.getParent()); File dir = new File(backupDirectory); if (!dir.exists()) dir.mkdirs(); } MiscUtilities.saveBackup(file,backups,backupPrefix, backupSuffix,backupDirectory,backupTimeDistance); } //}}} //{{{ _createInputStream() method public InputStream _createInputStream(Object session, String path, boolean ignoreErrors, Component comp) throws IOException { try { return new FileInputStream(path); } catch(IOException io) { if(ignoreErrors) return null; else throw io; } } //}}} //{{{ _createOutputStream() method public OutputStream _createOutputStream(Object session, String path, Component comp) throws IOException { return new FileOutputStream(path); } //}}} //{{{ _saveComplete() method public void _saveComplete(Object session, Buffer buffer, String path, Component comp) { int permissions = buffer.getIntegerProperty(PERMISSIONS_PROPERTY,0); setPermissions(path,permissions); } //}}} //{{{ Permission preservation code /** Code borrowed from j text editor (http://www.armedbear.org) */ /** I made some changes to make it support suid, sgid and sticky files */ //{{{ getPermissions() method /** * Returns numeric permissions of a file. On non-Unix systems, always * returns zero. * @since jEdit 3.2pre9 */ public static int getPermissions(String path) { int permissions = 0; if(jEdit.getBooleanProperty("chmodDisabled")) return permissions; if(OperatingSystem.isUnix()) { String[] cmdarray = { "ls", "-ld", path }; try { Process process = Runtime.getRuntime().exec(cmdarray); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String output = reader.readLine(); if(output != null) { String s = output.substring(1, 10); permissions = MiscUtilities .parsePermissions(s); } } // Feb 4 2000 5:30 PM // Catch Throwable here rather than Exception. // Kaffe's implementation of Runtime.exec throws java.lang.InternalError. catch (Throwable t) { } } return permissions; } //}}} //{{{ setPermissions() method /** * Sets numeric permissions of a file. On non-Unix platforms, * does nothing. * @since jEdit 3.2pre9 */ public static void setPermissions(String path, int permissions) { if(jEdit.getBooleanProperty("chmodDisabled")) return; if(permissions != 0) { if(OperatingSystem.isUnix()) { String[] cmdarray = { "chmod", Integer.toString(permissions, 8), path }; try { Process process = Runtime.getRuntime().exec(cmdarray); process.getInputStream().close(); process.getOutputStream().close(); process.getErrorStream().close(); // Jun 9 2004 12:40 PM // waitFor() hangs on some Java // implementations. /* int exitCode = process.waitFor(); if(exitCode != 0) Log.log(Log.NOTICE,FileVFS.class,"chmod exited with code " + exitCode); */ } // Feb 4 2000 5:30 PM // Catch Throwable here rather than Exception. // Kaffe's implementation of Runtime.exec throws java.lang.InternalError. catch (Throwable t) { } } } } //}}} //}}} //{{{ Private members private static FileSystemView fsView = FileSystemView.getFileSystemView(); //}}} }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy