diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/ChooseWorkspaceDialog.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/ChooseWorkspaceDialog.java index 05cde034235..e8807e90963 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/ChooseWorkspaceDialog.java +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/ChooseWorkspaceDialog.java @@ -474,9 +474,6 @@ protected String getUnexpectedPathHint() { } String normalisedPath = path.normalize().toString(); String normalisedPathWithSeperator = normalisedPath + File.separator; - if (!isWritable(path)) { - return NLS.bind(IDEWorkbenchMessages.ChooseWorkspaceDialog_NotWriteablePathWarning, normalisedPath); - } if (normalisedPathWithSeperator.contains(TILDE)) { return NLS.bind(IDEWorkbenchMessages.ChooseWorkspaceDialog_TildeNonExpandedWarning, normalisedPath); } @@ -484,23 +481,31 @@ protected String getUnexpectedPathHint() { && !workspaceLocation.equalsIgnoreCase(normalisedPathWithSeperator)) { return NLS.bind(IDEWorkbenchMessages.ChooseWorkspaceDialog_ResolvedAbsolutePath, normalisedPath); } + if (!maybeWritable(path)) { + return NLS.bind(IDEWorkbenchMessages.ChooseWorkspaceDialog_NotWriteablePathWarning, normalisedPath); + } } return ""; //$NON-NLS-1$ } - /** - * @param path - * @return - */ - private boolean isWritable(Path path) { - if (Files.exists(path)) { - return Files.isWritable(path); - } - Path parent = path.getParent(); - if (parent != null) { - return isWritable(parent); + /** the returned value may be wrong **/ + private boolean maybeWritable(Path path) { + try { + if (Files.exists(path)) { + // both java.io.File.canWrite() and + // java.nio.file.Files.isWritable(Path) + // can not be trusted on windows. they may return wrong values. + // for example JDK-8282720, JDK-8148211, JDK-8154915 + return Files.isWritable(path); + } + Path parent = path.getParent(); + if (parent == null) { + return false; + } + return maybeWritable(parent); + } catch (SecurityException se) { + return false; } - return true; } protected Composite createBrowseComposite(Composite parent) { @@ -545,7 +550,8 @@ protected Combo createPathCombo(Composite panel) { */ private boolean isValidPath(String path) { try { - return isWritable(new File(path).toPath()); + Path.of(path); + return true; } catch (InvalidPathException e) { return false; } diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties index d55a6f59376..3f9b127093c 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties @@ -1049,7 +1049,7 @@ ChooseWorkspaceDialog_recentWorkspaces=&Recent Workspaces ChooseWorkspaceDialog_ResolvedAbsolutePath=Full path: {0} ChooseWorkspaceDialog_TildeNonExpandedWarning=\u26A0\uFE0F '~' is not expanded, full path: {0} ChooseWorkspaceDialog_InvalidPathWarning=\u26A0\uFE0F The path is invalid on this system: {0} -ChooseWorkspaceDialog_NotWriteablePathWarning=\u26A0\uFE0F The path is not writable by the current user: {0} +ChooseWorkspaceDialog_NotWriteablePathWarning=\u26A0\uFE0F The path may not be writable by the current user: {0} ChooseWorkspaceDialog_useDefaultMessage=&Use this as the default and do not ask again ChooseWorkspaceWithSettingsDialog_SettingsGroupName=&Copy Settings