From 06bb64c597fb5a07ed1df6223be436a62fe4e2cc Mon Sep 17 00:00:00 2001 From: Martin Oberhuber < martin.oberhuber@windriver.com> Date: Tue, 3 Jun 2008 23:24:51 +0000 Subject: [PATCH] [235360][ftp][ssh][local] Return proper "Root" IHostFile --- .../services/files/ftp/FTPHostFile.java | 103 ++++++++++-------- .../services/files/ftp/FTPService.java | 11 +- .../local/files/LocalFileService.java | 10 +- .../services/ssh/files/SftpFileService.java | 20 ++-- .../services/ssh/files/SftpHostFile.java | 82 ++++++++------ .../FileServiceSubSystem.java | 4 +- 6 files changed, 142 insertions(+), 88 deletions(-) diff --git a/rse/plugins/org.eclipse.rse.services.files.ftp/src/org/eclipse/rse/internal/services/files/ftp/FTPHostFile.java b/rse/plugins/org.eclipse.rse.services.files.ftp/src/org/eclipse/rse/internal/services/files/ftp/FTPHostFile.java index 2c02ea29365..fc08fe3452b 100644 --- a/rse/plugins/org.eclipse.rse.services.files.ftp/src/org/eclipse/rse/internal/services/files/ftp/FTPHostFile.java +++ b/rse/plugins/org.eclipse.rse.services.files.ftp/src/org/eclipse/rse/internal/services/files/ftp/FTPHostFile.java @@ -22,6 +22,7 @@ * Martin Oberhuber (Wind River) - [204669] Fix ftp path concatenation on systems using backslash separator * Javier Montalvo Orus (Symbian) - [198692] FTP should mark files starting with "." as hidden * David McKnight (IBM) - [209593] [api] add support for "file permissions" and "owner" properties for unix files + * Martin Oberhuber (Wind River) - [235360][ftp][ssh][local] Return proper "Root" IHostFile *******************************************************************************/ package org.eclipse.rse.internal.services.files.ftp; @@ -39,7 +40,7 @@ import org.eclipse.rse.services.files.IHostFilePermissionsContainer; public class FTPHostFile implements IHostFile, IHostFilePermissionsContainer { - + private String _name; private String _parentPath; private boolean _isDirectory; @@ -53,11 +54,14 @@ public class FTPHostFile implements IHostFile, IHostFilePermissionsContainer private boolean _exists; private IHostFilePermissions _permissions; private FTPFile _ftpFile; - + public FTPHostFile(String parentPath, String name, boolean isDirectory, boolean isRoot, long lastModified, long size, boolean exists) { _parentPath = parentPath; _name = name; + if (name == null || name.length() == 0) { + throw new IllegalArgumentException(); + } _isDirectory = isDirectory; _lastModified = lastModified; _size = size; @@ -72,52 +76,52 @@ public class FTPHostFile implements IHostFile, IHostFilePermissionsContainer { _parentPath = parentPath; _ftpFile = ftpFile; - + _name = ftpFile.getName(); - + _isDirectory = ftpFile.isDirectory(); _isLink = ftpFile.isSymbolicLink(); _lastModified = ftpFile.getTimestamp().getTimeInMillis(); _size = ftpFile.getSize(); _isArchive = internalIsArchive(); - + _canRead = ftpFile.hasPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION); _canWrite = ftpFile.hasPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION); - + _isRoot = false; _exists = true; - + initPermissions(ftpFile); } - - - + + + public long getSize() { return _size; } - + public boolean isDirectory() { return _isDirectory; } - + public boolean isFile() { return !(_isDirectory || _isRoot); } - + public boolean isLink() { return _isLink; } - + public String getName() { return _name; } - + public boolean canRead() { return _canRead; } @@ -170,35 +174,46 @@ public class FTPHostFile implements IHostFile, IHostFilePermissionsContainer public boolean isRoot() { return _isRoot; - + } public String getParentPath() { return _parentPath; } - public void renameTo(String newAbsolutePath) + public void renameTo(String newAbsolutePath) { int i = newAbsolutePath.lastIndexOf("/"); //$NON-NLS-1$ - if (i == -1) - { + if (i == -1) { + //Rename inside the same parent folder. + //FIXME is this really what was desired here? Or would we rename Roots? + //Renaming Roots isn't possible, I'd think. _name = newAbsolutePath; } - else - { + else if (i == 0) { + // Renaming a root folder + if (newAbsolutePath.length()==1) { + //rename to root "/" -- should this work? + _parentPath = null; + _isRoot = true; + _name = newAbsolutePath; + } else { + _parentPath = "/"; //$NON-NLS-1$ + _name = newAbsolutePath.substring(i + 1); + } + } else { _parentPath = newAbsolutePath.substring(0, i); _name = newAbsolutePath.substring(i+1); } - _isArchive = internalIsArchive(); } - + public int getUserPermissions() { int userRead = 0; int userWrite = 0; int userExec = 0; - + //user if(_ftpFile!=null) { @@ -211,18 +226,18 @@ public class FTPHostFile implements IHostFile, IHostFilePermissionsContainer userRead = _canRead ? 1 : 0; userWrite = _canWrite ? 1 : 0; userExec = 0; - + } - + return userRead << 2 | userWrite << 1 | userExec; } - + public int getGroupPermissions() - { + { int groupRead = 0; int groupWrite = 0; int groupExec = 0; - + //group if(_ftpFile!=null) { @@ -230,16 +245,16 @@ public class FTPHostFile implements IHostFile, IHostFilePermissionsContainer groupWrite = _ftpFile.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION) ? 1 : 0; groupExec = _ftpFile.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION) ? 1 : 0; } - + return groupRead << 2 | groupWrite << 1 | groupExec; } - + public int getOtherPermissions() { int otherRead = 0; int otherWrite = 0; int otherExec = 0; - + //other if(_ftpFile!=null) { @@ -247,28 +262,28 @@ public class FTPHostFile implements IHostFile, IHostFilePermissionsContainer otherWrite = _ftpFile.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION) ? 1 : 0; otherExec = _ftpFile.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION) ? 1 : 0; } - + return otherRead << 2 | otherWrite << 1 | otherExec; } - - - - + + + + protected boolean internalIsArchive() { - return ArchiveHandlerManager.getInstance().isArchive(new File(getAbsolutePath())) + return ArchiveHandlerManager.getInstance().isArchive(new File(getAbsolutePath())) && !ArchiveHandlerManager.isVirtual(getAbsolutePath()); } - + public void setIsDirectory(boolean isDirectory) { _isDirectory = isDirectory; } - + public String getClassification() { String result; String linkTarget; - + if (isLink()) { result = "symbolic link"; //$NON-NLS-1$ if ((linkTarget = _ftpFile.getLink()) !=null) { @@ -304,13 +319,13 @@ public class FTPHostFile implements IHostFile, IHostFilePermissionsContainer _permissions.setPermission(IHostFilePermissions.PERM_GROUP_EXECUTE, ftpFile.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION)); _permissions.setPermission(IHostFilePermissions.PERM_OTHER_READ, ftpFile.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION)); _permissions.setPermission(IHostFilePermissions.PERM_OTHER_WRITE, ftpFile.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION)); - _permissions.setPermission(IHostFilePermissions.PERM_OTHER_EXECUTE, ftpFile.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION)); + _permissions.setPermission(IHostFilePermissions.PERM_OTHER_EXECUTE, ftpFile.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION)); _permissions.setUserOwner(ftpFile.getUser()); _permissions.setGroupOwner(ftpFile.getGroup()); } - + public IHostFilePermissions getPermissions() { return _permissions; } @@ -318,5 +333,5 @@ public class FTPHostFile implements IHostFile, IHostFilePermissionsContainer public void setPermissions(IHostFilePermissions permissions) { _permissions = permissions; } - + } diff --git a/rse/plugins/org.eclipse.rse.services.files.ftp/src/org/eclipse/rse/internal/services/files/ftp/FTPService.java b/rse/plugins/org.eclipse.rse.services.files.ftp/src/org/eclipse/rse/internal/services/files/ftp/FTPService.java index ccdd706b7e2..b9f19c25bd4 100644 --- a/rse/plugins/org.eclipse.rse.services.files.ftp/src/org/eclipse/rse/internal/services/files/ftp/FTPService.java +++ b/rse/plugins/org.eclipse.rse.services.files.ftp/src/org/eclipse/rse/internal/services/files/ftp/FTPService.java @@ -77,6 +77,7 @@ * Martin Oberhuber (Wind River) - [218040] FTP should support permission modification * Martin Oberhuber (Wind River) - [234045] FTP Permission Error Handling * Martin Oberhuber (Wind River) - [235463][ftp][dstore] Incorrect case sensitivity reported on windows-remote + * Martin Oberhuber (Wind River) - [235360][ftp][ssh][local] Return proper "Root" IHostFile ********************************************************************************/ package org.eclipse.rse.internal.services.files.ftp; @@ -321,6 +322,8 @@ public class FTPService extends AbstractFileService implements IFTPService, IFil * @throws SystemMessageException if information is lost */ protected String checkEncoding(String s) throws SystemMessageException { + if (s == null || s.length() == 0) + return s; String encoding = _controlEncoding!=null ? _controlEncoding : getFTPClient().getControlEncoding(); try { byte[] bytes = s.getBytes(encoding); @@ -574,6 +577,12 @@ public class FTPService extends AbstractFileService implements IFTPService, IFil */ protected FTPHostFile getFileInternal(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException { + boolean isRoot = (remoteParent == null || remoteParent.length() == 0); + if (isRoot) { + // FTP doesn't really support getting properties of Roots yet. For + // now, return the root and claim it's existing. + return new FTPHostFile(remoteParent, fileName, true, true, 0, 0, true); + } remoteParent = checkEncoding(remoteParent); fileName = checkEncoding(fileName); if (monitor!=null){ @@ -999,7 +1008,7 @@ public class FTPService extends AbstractFileService implements IFTPService, IFil //Returning null in this case is safest, see also SftpFileService. return null; } - return new FTPHostFile("",_userHome,true,true,0,0,true); //$NON-NLS-1$ + return new FTPHostFile(null, _userHome, true, true, 0, 0, true); } /* diff --git a/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/files/LocalFileService.java b/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/files/LocalFileService.java index cdbdd0ee9bc..323e2b029ff 100644 --- a/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/files/LocalFileService.java +++ b/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/files/LocalFileService.java @@ -39,6 +39,7 @@ * David McKnight (IBM) - [231211] Local xml file not opened when workspace encoding is different from local system encoding * Radoslav Gerganov (ProSyst) - [230919] IFileService.delete() should not return a boolean * Martin Oberhuber (Wind River) - [233993] Improve EFS error reporting + * Martin Oberhuber (Wind River) - [235360][ftp][ssh][local] Return proper "Root" IHostFile *******************************************************************************/ package org.eclipse.rse.internal.services.local.files; @@ -782,7 +783,7 @@ public class LocalFileService extends AbstractFileService implements ILocalServi { String userHome =System.getProperty("user.home"); //$NON-NLS-1$ File userHomeFile = new File(userHome); - return new LocalHostFile(userHomeFile); + return new LocalHostFile(userHomeFile, (userHomeFile.getParent() == null)); } @@ -831,7 +832,8 @@ public class LocalFileService extends AbstractFileService implements ILocalServi boolean isVirtualParent = false; boolean isArchiveParent = false; - if (remoteParent != null) { + boolean isRoot = (remoteParent == null || remoteParent.length() == 0); + if (!isRoot) { File remoteParentFile = new File(remoteParent); if (!remoteParentFile.exists()) { isVirtualParent = ArchiveHandlerManager.isVirtual(remoteParent); @@ -841,8 +843,8 @@ public class LocalFileService extends AbstractFileService implements ILocalServi } if (!isVirtualParent && !isArchiveParent) { - File file = remoteParent==null ? new File(name) : new File(remoteParent, name); - return new LocalHostFile(file); + File file = isRoot ? new File(name) : new File(remoteParent, name); + return new LocalHostFile(file, isRoot); } else { diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/internal/services/ssh/files/SftpFileService.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/internal/services/ssh/files/SftpFileService.java index 7f54379d1ab..c2bc18910c7 100644 --- a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/internal/services/ssh/files/SftpFileService.java +++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/internal/services/ssh/files/SftpFileService.java @@ -31,6 +31,7 @@ * Martin Oberhuber (Wind River) - [218042] Support UNIX permission modification on ssh * Martin Oberhuber (Wind River) - [233651] Make ssh delete throw proper exceptions * Martin Oberhuber (Wind River) - [235477][ssh] SftpFileService.createFolder() fails for file named "a?*" + * Martin Oberhuber (Wind River) - [235360][ftp][ssh][local] Return proper "Root" IHostFile *******************************************************************************/ package org.eclipse.rse.internal.services.ssh.files; @@ -446,6 +447,10 @@ public class SftpFileService extends AbstractFileService implements ISshService, */ protected String concat(String parentDir, String fileName) { // See also {@link SftpHostFile#getAbsolutePath()} + if (parentDir == null || parentDir.length() == 0) { + // Looking at a Root + return fileName; + } StringBuffer path = new StringBuffer(parentDir); if (!parentDir.endsWith("/")) //$NON-NLS-1$ { @@ -483,7 +488,8 @@ public class SftpFileService extends AbstractFileService implements ISshService, throw new SystemLockTimeoutException(Activator.PLUGIN_ID); } if (node==null) { - node = new SftpHostFile(remoteParent, fileName, false, false, false, 0, 0); + boolean isRoot = (remoteParent == null || remoteParent.length() == 0); + node = new SftpHostFile(remoteParent, fileName, false, isRoot, false, 0, 0); node.setExists(false); } return node; @@ -566,8 +572,9 @@ public class SftpFileService extends AbstractFileService implements ISshService, SftpATTRS attrsTarget = attrs; String linkTarget=null; String canonicalPath = null; - if (attrs.isLink()) { - //check if the link points to a directory + boolean isRoot = (parentPath == null || parentPath.length() == 0); + if (attrs.isLink() && !isRoot) { + //check if the link points to a directory. Roots cannot be Links. try { String fullPath = concat(parentPath, fileName); boolean readlinkDone = false; @@ -615,8 +622,7 @@ public class SftpFileService extends AbstractFileService implements ISshService, } } - - SftpHostFile node = new SftpHostFile(parentPath, fileName, attrsTarget.isDir(), false, attrs.isLink(), 1000L * attrs.getMTime(), attrs.getSize()); + SftpHostFile node = new SftpHostFile(parentPath, fileName, attrsTarget.isDir(), isRoot, attrs.isLink(), 1000L * attrs.getMTime(), attrs.getSize()); if (linkTarget!=null) { node.setLinkTarget(linkTarget); } @@ -848,7 +854,7 @@ public class SftpFileService extends AbstractFileService implements ISshService, //Returning the home path as a Root is the safest we can do, since it will //let users know what the home path is, and the "My Home" filter will be //set to correct target. See also bug 204710. - return new SftpHostFile("", fUserHome, true, true, false, 0, 0); //$NON-NLS-1$ + return new SftpHostFile(null, fUserHome, true, true, false, 0, 0); } } //Bug 203490, bug 204710: Could not determine user home @@ -856,7 +862,7 @@ public class SftpFileService extends AbstractFileService implements ISshService, } public IHostFile[] getRoots(IProgressMonitor monitor) { - IHostFile root = new SftpHostFile("/", "/", true, true, false, 0, 0); //$NON-NLS-1$ //$NON-NLS-2$ + IHostFile root = new SftpHostFile(null, "/", true, true, false, 0, 0); //$NON-NLS-1$ return new IHostFile[] { root }; } diff --git a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/internal/services/ssh/files/SftpHostFile.java b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/internal/services/ssh/files/SftpHostFile.java index 0a480255f3f..775a5c2205d 100644 --- a/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/internal/services/ssh/files/SftpHostFile.java +++ b/rse/plugins/org.eclipse.rse.services.ssh/src/org/eclipse/rse/internal/services/ssh/files/SftpHostFile.java @@ -7,13 +7,14 @@ * * Initial Contributors: * The following IBM employees contributed to the Remote System Explorer - * component that contains this file: David McKnight, Kushal Munir, - * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. - * + * * Contributors: * Martin Oberhuber (Wind River) - Adapted from FTPHostFile. - * David McKnight (IBM) - [209593] [api] add support for "file permissions" and "owner" properties for unix files + * David McKnight (IBM) - [209593] [api] add support for "file permissions" and "owner" properties for unix files + * Martin Oberhuber (Wind River) - [235360][ftp][ssh][local] Return proper "Root" IHostFile *******************************************************************************/ package org.eclipse.rse.internal.services.ssh.files; @@ -42,13 +43,16 @@ public class SftpHostFile implements IHostFile, IHostFilePermissionsContainer { private String fLinkTarget; private String fCanonicalPath; private String[] fExtended = null; - + private IHostFilePermissions _permissions = null; - + //TODO just re-use or extend FTPHostFile instead of copying here? public SftpHostFile(String parentPath, String name, boolean isDirectory, boolean isRoot, boolean isLink, long lastModified, long size) { fParentPath = parentPath; fName = name; + if (name == null || name.length() == 0) { + throw new IllegalArgumentException(); + } fIsDirectory = isDirectory; fIsRoot = isRoot; fLastModified = lastModified; @@ -58,34 +62,34 @@ public class SftpHostFile implements IHostFile, IHostFilePermissionsContainer { } public String getName() { - return fName; + return fName; } - + public boolean isHidden() { String name = getName(); return name.charAt(0) == '.'; } - + public String getParentPath() { return fParentPath; } - + public boolean isDirectory() { return fIsDirectory; } - + public boolean isFile() { return !(fIsDirectory || fIsRoot); } - + public boolean isRoot() { return fIsRoot; } - + public void setExists(boolean b) { fExists = b; } - + public boolean exists() { return fExists; } @@ -115,9 +119,25 @@ public class SftpHostFile implements IHostFile, IHostFilePermissionsContainer { public void renameTo(String newAbsolutePath) { int i = newAbsolutePath.lastIndexOf("/"); //$NON-NLS-1$ if (i == -1) { + //Rename inside the same parent folder. + //FIXME is this really what was desired here? Or would we rename Roots? + //Renaming Roots isn't possible, I'd think. fName = newAbsolutePath; } - else { + else if (i == 0) { + // Renaming a root folder + if (newAbsolutePath.length()==1) { + //rename to root "/" -- should this work? + fParentPath = null; + fIsRoot = true; + fName = newAbsolutePath; + } else { + fParentPath = "/"; //$NON-NLS-1$ + fName = newAbsolutePath.substring(i + 1); + } + fParentPath = "/"; //$NON-NLS-1$ + fName = newAbsolutePath.substring(i + 1); + } else { fParentPath = newAbsolutePath.substring(0, i); fName = newAbsolutePath.substring(i+1); } @@ -125,30 +145,30 @@ public class SftpHostFile implements IHostFile, IHostFilePermissionsContainer { } protected boolean internalIsArchive() { - return ArchiveHandlerManager.getInstance().isArchive(new File(getAbsolutePath())) + return ArchiveHandlerManager.getInstance().isArchive(new File(getAbsolutePath())) && !ArchiveHandlerManager.isVirtual(getAbsolutePath()); } - + public boolean isArchive() { return fIsArchive; } - + public boolean isLink() { return fIsLink; } - + public void setLinkTarget(String linkTarget) { fLinkTarget = linkTarget; } - + public String getLinkTarget() { return fLinkTarget; } - + public void setCanonicalPath(String canonicalPath) { fCanonicalPath = canonicalPath; } - + public String getCanonicalPath() { if (fCanonicalPath==null) { return getAbsolutePath(); @@ -156,10 +176,10 @@ public class SftpHostFile implements IHostFile, IHostFilePermissionsContainer { return fCanonicalPath; } } - - /** + + /** * Set Extended data as key,value pairs. - * + * * The data is maintained as a String array, where every element * with an even index refers to a key, and the next element * refers to its value. Example @@ -167,17 +187,17 @@ public class SftpHostFile implements IHostFile, IHostFilePermissionsContainer { * extended[1] = "joe,tim" * extended[2] = "version" * extended[3] = "/main/3" - * - * @param extended String[] array of key,value pairs + * + * @param extended String[] array of key,value pairs */ public void setExtendedData(String[] extended) { fExtended = extended; } - + /** * Return extended data as name,value pairs. * @see #setExtendedData(String[]) - * + * * @return String[] array of key,value pairs */ public String[] getExtendedData() { @@ -234,12 +254,12 @@ public class SftpHostFile implements IHostFile, IHostFilePermissionsContainer { public boolean canExecute() { return fIsExecutable; } - + public IHostFilePermissions getPermissions() { return _permissions; } public void setPermissions(IHostFilePermissions permissions) { - _permissions = permissions; + _permissions = permissions; } } diff --git a/rse/plugins/org.eclipse.rse.subsystems.files.core/src/org/eclipse/rse/subsystems/files/core/servicesubsystem/FileServiceSubSystem.java b/rse/plugins/org.eclipse.rse.subsystems.files.core/src/org/eclipse/rse/subsystems/files/core/servicesubsystem/FileServiceSubSystem.java index b6bb56c8257..5fddca12825 100644 --- a/rse/plugins/org.eclipse.rse.subsystems.files.core/src/org/eclipse/rse/subsystems/files/core/servicesubsystem/FileServiceSubSystem.java +++ b/rse/plugins/org.eclipse.rse.subsystems.files.core/src/org/eclipse/rse/subsystems/files/core/servicesubsystem/FileServiceSubSystem.java @@ -39,6 +39,7 @@ * Martin Oberhuber (Wind River) - [221211] Fix markStale() for delete() operation with exceptions * David Dykstal (IBM) - [230821] fix IRemoteFileSubSystem API to be consistent with IFileService * Martin Oberhuber (Wind River) - [234038] Mark IRemoteFile stale when changing permissions + * Martin Oberhuber (Wind River) - [235360][ftp][ssh][local] Return proper "Root" IHostFile *******************************************************************************/ package org.eclipse.rse.subsystems.files.core.servicesubsystem; @@ -326,8 +327,9 @@ public class FileServiceSubSystem extends RemoteFileSubSystem implements IFileSe } IRemoteFile parent = null; - if (!userHome.getParentPath().equals(".")) //$NON-NLS-1$ + if (!".".equals(userHome.getParentPath())) //$NON-NLS-1$ { + //note: parent path can be "null" if userHome is a Root try { //parent = getRemoteFileObject(userHome.getParentPath());