From 72ed306d20458e240c15de2d97ee97c792e32001 Mon Sep 17 00:00:00 2001 From: Martin Oberhuber < martin.oberhuber@windriver.com> Date: Mon, 26 May 2008 17:55:07 +0000 Subject: [PATCH] [233993] Improve EFS error reporting --- .../rse/internal/efs/RSEFileStoreImpl.java | 106 +++++++++++------- .../local/files/LocalFileService.java | 101 ++++++++++++----- .../SystemElementNotFoundException.java | 32 +++++- 3 files changed, 165 insertions(+), 74 deletions(-) diff --git a/rse/plugins/org.eclipse.rse.efs/src/org/eclipse/rse/internal/efs/RSEFileStoreImpl.java b/rse/plugins/org.eclipse.rse.efs/src/org/eclipse/rse/internal/efs/RSEFileStoreImpl.java index cb47e5e0310..fa442b18ebd 100644 --- a/rse/plugins/org.eclipse.rse.efs/src/org/eclipse/rse/internal/efs/RSEFileStoreImpl.java +++ b/rse/plugins/org.eclipse.rse.efs/src/org/eclipse/rse/internal/efs/RSEFileStoreImpl.java @@ -28,6 +28,7 @@ * Kevin Doyle (IBM) - [210673] [efs][nls] Externalize Strings in RSEFileStore and RSEFileStoreImpl * Timur Shipilov (Xored) - [224540] [efs] RSEFileStore.mkdir(EFS.NONE, null) doesn't create parent folder * David Dykstal (IBM) [230821] fix IRemoteFileSubSystem API to be consistent with IFileService + * Martin Oberhuber (Wind River) - [233993] Improve EFS error reporting ********************************************************************************/ package org.eclipse.rse.internal.efs; @@ -52,6 +53,7 @@ import org.eclipse.rse.core.RSECorePlugin; import org.eclipse.rse.core.model.IHost; import org.eclipse.rse.core.model.ISystemRegistry; import org.eclipse.rse.core.subsystems.RemoteChildrenContentsType; +import org.eclipse.rse.services.clientserver.messages.SystemElementNotFoundException; import org.eclipse.rse.services.clientserver.messages.SystemMessageException; import org.eclipse.rse.services.files.IFileService; import org.eclipse.rse.services.files.IHostFile; @@ -179,7 +181,7 @@ public class RSEFileStoreImpl extends FileStore return unconnected; } - + /** * Return the best available remote file subsystem for a connection. * Criteria are: @@ -189,7 +191,7 @@ public class RSEFileStoreImpl extends FileStore *
  • An unconnected FileServiceSubsystem
  • *
  • An unconnected IRemoteFileSubSystem
  • * - * + * * @param host the connection to check * @return an IRemoteFileSubSystem for the given connection, or * null if no IRemoteFileSubSystem is configured. @@ -556,6 +558,24 @@ public class RSEFileStoreImpl extends FileStore return exceptionText; } + /** + * Re-interpret RSE internal exceptions into proper EFS CoreException. + * + * @param e Original exception from RSE SubSystems + * @param codeHint hint as to what the EFS Error Code might be + * @throws CoreException create CoreException according to EFS specification + */ + private void rethrowCoreException(Exception e, int codeHint) throws CoreException { + //default pluginId to the EFS provider; override by root if possible + String pluginId = Activator.getDefault().getBundle().getSymbolicName(); + String msg = getExceptionMessage(toString(), e); + int code = codeHint; + if (e instanceof SystemElementNotFoundException) { + code = EFS.ERROR_NOT_EXISTS; + } + throw new CoreException(new Status(IStatus.ERROR, pluginId, code, msg, e)); + } + /* * (non-Javadoc) * @see org.eclipse.core.filesystem.provider.FileStore#putInfo(org.eclipse.core.filesystem.IFileInfo, int, org.eclipse.core.runtime.IProgressMonitor) @@ -566,16 +586,14 @@ public class RSEFileStoreImpl extends FileStore IRemoteFileSubSystem subSys = remoteFile.getParentRemoteFileSubSystem(); try { if ((options & EFS.SET_ATTRIBUTES) != 0) { - //We cannot currently write isExecutable(), isHidden() + // We cannot currently write isExecutable(), isHidden() subSys.setReadOnly(remoteFile, info.getAttribute(EFS.ATTRIBUTE_READ_ONLY), monitor); } if ((options & EFS.SET_LAST_MODIFIED) != 0) { subSys.setLastModified(remoteFile, info.getLastModified(), monitor); } - } catch(Exception e) { - throw new CoreException(new Status(IStatus.ERROR, - Activator.getDefault().getBundle().getSymbolicName(), - getExceptionMessage(toString(), e), e)); + } catch (Exception e) { + rethrowCoreException(e, EFS.ERROR_WRITE); } } @@ -591,7 +609,8 @@ public class RSEFileStoreImpl extends FileStore if (remoteFile.isDirectory()) { throw new CoreException(new Status(IStatus.ERROR, Activator.getDefault().getBundle().getSymbolicName(), - Messages.CANNOT_OPEN_STREAM_ON_FOLDER)); + EFS.ERROR_WRONG_TYPE, + Messages.CANNOT_OPEN_STREAM_ON_FOLDER, null)); } if (remoteFile.isFile()) { @@ -600,13 +619,15 @@ public class RSEFileStoreImpl extends FileStore } catch (SystemMessageException e) { cacheRemoteFile(null); - throw new CoreException(new Status(IStatus.ERROR, - Activator.getDefault().getBundle().getSymbolicName(), - getExceptionMessage(null, e), e)); + rethrowCoreException(e, EFS.ERROR_READ); } } - return null; + //file does not exist, apparently + //TODO use Java MessageFormat for embedding filename in message + throw new CoreException(new Status(IStatus.ERROR, Activator.getDefault().getBundle().getSymbolicName(), + // EFS.ERROR_NOT_EXISTS, + EFS.ERROR_READ, Messages.FILE_STORE_DOES_NOT_EXIST + ": " + toString(), null)); //$NON-NLS-1$ } /* @@ -615,37 +636,49 @@ public class RSEFileStoreImpl extends FileStore */ public IFileStore mkdir(int options, IProgressMonitor monitor) throws CoreException { - if (options == EFS.NONE) { - IFileStore parent = getParent(); - if (parent != null) { - parent.mkdir(options, monitor); - } - } + //TODO Check should be done by IRemoteFileSubSystem.createFolders() + //if ((options & EFS.SHALLOW)!=0) { + // IFileStore parent = getParent(); + // if (parent == null) || !parent.{ + // parent.mkdir(options, monitor); + // } + //} cacheRemoteFile(null); IRemoteFile remoteFile = getRemoteFileObject(monitor, false); if (remoteFile==null) { throw new CoreException(new Status(IStatus.ERROR, Activator.getDefault().getBundle().getSymbolicName(), - Messages.COULD_NOT_GET_REMOTE_FILE)); + EFS.ERROR_NOT_EXISTS, + Messages.COULD_NOT_GET_REMOTE_FILE, null)); } IRemoteFileSubSystem subSys = remoteFile.getParentRemoteFileSubSystem(); if (!remoteFile.exists()) { try { - remoteFile = subSys.createFolder(remoteFile, monitor); + if ((options & EFS.SHALLOW) != 0) { + //TODO following check should be obsolete + if (!remoteFile.getParentRemoteFile().exists()) { + throw new CoreException(new Status(IStatus.ERROR, + Activator.getDefault().getBundle().getSymbolicName(), + EFS.ERROR_WRITE, + Messages.FILE_STORE_DOES_NOT_EXIST, null)); + } + remoteFile = subSys.createFolder(remoteFile, monitor); + } else { + remoteFile = subSys.createFolders(remoteFile, monitor); + } cacheRemoteFile(remoteFile); } catch (SystemMessageException e) { - throw new CoreException(new Status(IStatus.ERROR, - Activator.getDefault().getBundle().getSymbolicName(), - getExceptionMessage(null, e), e)); + rethrowCoreException(e, EFS.ERROR_WRITE); } return _store; } else if (remoteFile.isFile()) { throw new CoreException(new Status(IStatus.ERROR, Activator.getDefault().getBundle().getSymbolicName(), - Messages.FILE_NAME_EXISTS)); + EFS.ERROR_WRONG_TYPE, + Messages.FILE_NAME_EXISTS, null)); } else { return _store; @@ -671,9 +704,7 @@ public class RSEFileStoreImpl extends FileStore cacheRemoteFile(remoteFile); } catch (SystemMessageException e) { - throw new CoreException(new Status(IStatus.ERROR, - Activator.getDefault().getBundle().getSymbolicName(), - getExceptionMessage(null, e), e)); + rethrowCoreException(e, EFS.ERROR_WRITE); } } @@ -688,20 +719,18 @@ public class RSEFileStoreImpl extends FileStore return subSys.getOutputStream(remoteFile.getParentPath(), remoteFile.getName(), options, monitor); } catch (SystemMessageException e) { - throw new CoreException(new Status(IStatus.ERROR, - Activator.getDefault().getBundle().getSymbolicName(), - Messages.CANNOT_OPEN_STREAM_ON_FOLDER, e)); + rethrowCoreException(e, EFS.ERROR_WRITE); } } else if (remoteFile.isDirectory()) { throw new CoreException(new Status(IStatus.ERROR, Activator.getDefault().getBundle().getSymbolicName(), - Messages.CANNOT_OPEN_STREAM_ON_FOLDER)); - } - else { - //TODO check what to do for symbolic links and other strange stuff - return null; + EFS.ERROR_WRONG_TYPE, + Messages.CANNOT_OPEN_STREAM_ON_FOLDER, null)); } + //Fallback: No file, no folder? + //TODO check what to do for symbolic links and other strange stuff + return null; } /* @@ -716,10 +745,11 @@ public class RSEFileStoreImpl extends FileStore cacheRemoteFile(null); subSys.delete(remoteFile, monitor); } + catch (SystemElementNotFoundException e) { + /* not considered an error by EFS -- ignore */ + } catch (SystemMessageException e) { - throw new CoreException(new Status(IStatus.ERROR, - Activator.getDefault().getBundle().getSymbolicName(), - getExceptionMessage(null, e), e)); + rethrowCoreException(e, EFS.ERROR_DELETE); } } } \ No newline at end of file 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 2ea90efce4e..cdbdd0ee9bc 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 @@ -38,7 +38,7 @@ * Martin Oberhuber (Wind River) - [226262] Make IService IAdaptable * 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 - * David McKnight (IBM) - [233373] NPE when deleting a file from a read-only folder on Local + * Martin Oberhuber (Wind River) - [233993] Improve EFS error reporting *******************************************************************************/ package org.eclipse.rse.internal.services.local.files; @@ -88,6 +88,7 @@ import org.eclipse.rse.services.clientserver.messages.SystemElementNotFoundExcep import org.eclipse.rse.services.clientserver.messages.SystemMessage; import org.eclipse.rse.services.clientserver.messages.SystemMessageException; import org.eclipse.rse.services.clientserver.messages.SystemOperationCancelledException; +import org.eclipse.rse.services.clientserver.messages.SystemOperationFailedException; import org.eclipse.rse.services.files.AbstractFileService; import org.eclipse.rse.services.files.HostFilePermissions; import org.eclipse.rse.services.files.IFilePermissionsService; @@ -476,7 +477,7 @@ public class LocalFileService extends AbstractFileService implements ILocalServi String systemEncoding = SystemEncodingUtil.getInstance().getEnvironmentEncoding(); boolean sizeCheck = !isBinary && systemEncoding.equals(hostEncoding); - + if (sizeCheck && (destinationFile.length() != file.length())) { throw new SystemOperationCancelledException(); // System.err.println("local.upload: size mismach on "+destinationFile.getAbsolutePath()); //$NON-NLS-1$ @@ -1048,17 +1049,15 @@ public class LocalFileService extends AbstractFileService implements ILocalServi { result = fileToDelete.delete(); } - if (!result){ - if (fileToDelete.exists()) { - // Deletion failed without specification why... likely a Security - // problem? - // TODO we'll want to wrap a message with the IOException at some point after - // 3.0.1 - throw new RemoteFileSecurityException(new IOException()); - } - else { - throw new SystemElementNotFoundException(fileToDelete.getAbsolutePath(), "delete"); //$NON-NLS-1$ - } + if (!result) { + if (fileToDelete.exists()) { + // Deletion failed without specification why... likely a Security + // problem, or an open file in the files to be deleted. + // TODO Externalize Message + throw new SystemOperationFailedException(Activator.PLUGIN_ID, "Failed to delete: " + fileToDelete.getAbsolutePath()); + } else { + throw new SystemElementNotFoundException(fileToDelete.getAbsolutePath(), "delete"); + } } } @@ -1548,10 +1547,17 @@ public class LocalFileService extends AbstractFileService implements ILocalServi } } - public void setLastModified(String parent, String name, long timestamp, IProgressMonitor monitor) + public void setLastModified(String parent, String name, long timestamp, IProgressMonitor monitor) throws SystemMessageException { File file = new File(parent, name); - file.setLastModified(timestamp); + if (!file.setLastModified(timestamp)) { + if (!file.exists()) { + // TODO externalize message + throw new SystemElementNotFoundException(Activator.PLUGIN_ID, file.getAbsolutePath(), "setLastModified"); + } else { + throw new SystemOperationFailedException(Activator.PLUGIN_ID, "setLastModified: " + file.getAbsolutePath()); + } + } } public void setReadOnly(String parent, String name, @@ -1559,10 +1565,11 @@ public class LocalFileService extends AbstractFileService implements ILocalServi { File file = new File(parent, name); if (!file.exists()) { - String pluginId = Activator.PLUGIN_ID; - String messageText = "File does not exist"; - SimpleSystemMessage message = new SimpleSystemMessage(pluginId, IStatus.ERROR, messageText); - throw new SystemMessageException(message); + //TODO Externalize message, and/or centralize e.g. RemoteFileNotFoundException + //See org.eclipse.core.filesystem/src/org/eclipse/core/internal/filesystem/Messages.java - fileNotFound + String messageText = "File not found"; + //TODO throw new RemoteFileNotFoundException + throw new SystemElementNotFoundException(Activator.PLUGIN_ID, file.getAbsolutePath(), "setReadOnly"); } if (readOnly != file.canWrite()) { return; @@ -1570,15 +1577,15 @@ public class LocalFileService extends AbstractFileService implements ILocalServi if (readOnly) { if (!file.setReadOnly()) { - String pluginId = Activator.PLUGIN_ID; - String messageText = "Cannot set file read only"; - SimpleSystemMessage message = new SimpleSystemMessage(pluginId, IStatus.ERROR, messageText); - throw new SystemMessageException(message); + //TODO Externalize message + throw new SystemOperationFailedException(Activator.PLUGIN_ID, "Failed to setReadOnly: " + file.getAbsolutePath()); } return; } else { + Exception remoteException = null; + String remoteError = ""; //$NON-NLS-1$ if (!_isWindows) { // make this read-write @@ -1591,15 +1598,19 @@ public class LocalFileService extends AbstractFileService implements ILocalServi { Process p = Runtime.getRuntime().exec(cmd); exitValue = p.waitFor(); + if (p.getErrorStream().available() > 0) { + remoteError = ": " + new BufferedReader(new InputStreamReader(p.getErrorStream())).readLine(); //$NON-NLS-1$ + } else if (p.getInputStream().available() > 0) { + remoteError = ": " + new BufferedReader(new InputStreamReader(p.getInputStream())).readLine(); //$NON-NLS-1$ + } } catch (Exception e) { + remoteException = e; } if (exitValue != 0) { - String pluginId = Activator.PLUGIN_ID; - String messageText = "Cannot set file read-write"; - SimpleSystemMessage message = new SimpleSystemMessage(pluginId, IStatus.ERROR, messageText); - throw new SystemMessageException(message); + //TODO Externalize message + throw new SystemOperationFailedException(Activator.PLUGIN_ID, "Failed to setWritable: " + remoteError, remoteException); } } // windows version @@ -1614,17 +1625,31 @@ public class LocalFileService extends AbstractFileService implements ILocalServi { Process p = Runtime.getRuntime().exec(cmd); exitValue = p.waitFor(); + if (p.getErrorStream().available() > 0) { + remoteError = ": " + new BufferedReader(new InputStreamReader(p.getErrorStream())).readLine(); //$NON-NLS-1$ + } else if (p.getInputStream().available() > 0) { + remoteError = ": " + new BufferedReader(new InputStreamReader(p.getInputStream())).readLine(); //$NON-NLS-1$ + } } catch (Exception e) { + remoteException = e; } if (exitValue != 0) { - String pluginId = Activator.PLUGIN_ID; - String messageText = "Cannot set file read-write"; - SimpleSystemMessage message = new SimpleSystemMessage(pluginId, IStatus.ERROR, messageText); - throw new SystemMessageException(message); + //TODO Externalize String + throw new SystemOperationFailedException(Activator.PLUGIN_ID, "Failed to setWritable: " + remoteError, remoteException); } } + //Verify that it actually worked + if (!file.canWrite()) { + if (remoteError.length() == 0) { + // TODO Externalize String + remoteError = "Failed to setWritable: " + file.getAbsolutePath(); + } else { + remoteError = remoteError.substring(2); + } + throw new SystemOperationFailedException(Activator.PLUGIN_ID, remoteError); + } } } @@ -1641,6 +1666,13 @@ public class LocalFileService extends AbstractFileService implements ILocalServi try { stream = new FileInputStream(file); } + catch (FileNotFoundException e) { + if (!file.exists()) { + throw new SystemElementNotFoundException(Activator.PLUGIN_ID, file.getAbsolutePath(), "getInputStream"); + } else { + throw new RemoteFileIOException(e); + } + } catch (Exception e) { throw new RemoteFileIOException(e); } @@ -1673,6 +1705,13 @@ public class LocalFileService extends AbstractFileService implements ILocalServi stream = new FileOutputStream(file, true); } } + catch (FileNotFoundException e) { + if (!file.exists()) { + throw new SystemElementNotFoundException(Activator.PLUGIN_ID, file.getAbsolutePath(), "getOutputStream"); + } else { + throw new RemoteFileIOException(e); + } + } catch (Exception e) { throw new RemoteFileIOException(e); } diff --git a/rse/plugins/org.eclipse.rse.services/clientserver/org/eclipse/rse/services/clientserver/messages/SystemElementNotFoundException.java b/rse/plugins/org.eclipse.rse.services/clientserver/org/eclipse/rse/services/clientserver/messages/SystemElementNotFoundException.java index a6c78adb560..43dea579c70 100644 --- a/rse/plugins/org.eclipse.rse.services/clientserver/org/eclipse/rse/services/clientserver/messages/SystemElementNotFoundException.java +++ b/rse/plugins/org.eclipse.rse.services/clientserver/org/eclipse/rse/services/clientserver/messages/SystemElementNotFoundException.java @@ -7,6 +7,7 @@ * * Contributors: * Martin Oberhuber (Wind River) - initial API and implementation + * Martin Oberhuber (Wind River) - [233993] Improve EFS error reporting *******************************************************************************/ package org.eclipse.rse.services.clientserver.messages; @@ -21,7 +22,7 @@ import org.eclipse.rse.services.clientserver.IClientServerConstants; * but that element did not exist. Like trying to delete a file that does not * exist. The framework may treat such an exception differently than other kinds * of exceptions. - * + * * @since 3.0 */ public class SystemElementNotFoundException extends SystemMessageException { @@ -32,19 +33,40 @@ public class SystemElementNotFoundException extends SystemMessageException { */ private static final long serialVersionUID = 1L; + /** + * Constructor for subclasses to use custom messages. + * + * @param msg A SystemMessage. + */ + public SystemElementNotFoundException(SystemMessage msg) { + super(msg); + } + /** * Constructor. * * @param element an Absolute Path for the element that could not be found. + * @param operation Operation about to be performed that failed */ public SystemElementNotFoundException(String element, String operation) { - super(getMyMessage(element, operation)); + super(getMyMessage(IClientServerConstants.PLUGIN_ID, element, operation)); } - private static SystemMessage getMyMessage(String element, String operation) { - //TODO generate an internal backtrace and attach to the message + /** + * Constructor. + * + * @param pluginId ID of plugin in which the failure occurred + * @param element an Absolute Path for the element that could not be found. + * @param operation Operation about to be performed that failed + */ + public SystemElementNotFoundException(String pluginId, String element, String operation) { + super(getMyMessage(pluginId, element, operation)); + } + + private static SystemMessage getMyMessage(String pluginId, String element, String operation) { + //TODO generate an internal backtrace and attach to the message? String msgText = NLS.bind(CommonMessages.MSG_ELEMENT_NOT_FOUND, operation, element); - SystemMessage msg = new SimpleSystemMessage(IClientServerConstants.PLUGIN_ID, + SystemMessage msg = new SimpleSystemMessage(pluginId, ICommonMessageIds.MSG_ELEMENT_NOT_FOUND, IStatus.ERROR, msgText); return msg; }