Skip to content

Commit

Permalink
Add check for valid Dart SDK to preference page (#99)
Browse files Browse the repository at this point in the history
closes #83

Signed-off-by: Jonas Hungershausen <jonas.hungershausen@vogella.com>
  • Loading branch information
Jonas Hungershausen committed Jul 16, 2019
1 parent fb47adf commit 6bfd1d8
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 23 deletions.
Expand Up @@ -13,11 +13,12 @@
*******************************************************************************/
package org.eclipse.dartboard.preference;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.dartboard.Constants;
import org.eclipse.dartboard.Messages;
Expand Down Expand Up @@ -107,32 +108,18 @@ public boolean performOk() {
* @return
*/
private Path getPath(String location) {

if (dartSDKLocationEditor.isValid()) {
Path path = null;
try {
path = Paths.get(location);
path = path.toRealPath();
boolean isWindows = Platform.OS_WIN32.equals(Platform.getOS());
path = Paths.get(location + "bin" + File.separator + (isWindows ? "dart.exe" : "dart")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
// Since we append /bin/dart to resolve the symbolic links, we need to get 2
// levels up here.
path = path.toRealPath().toAbsolutePath().getParent().getParent();
} catch (IOException e) {
LOG.error("Couldn't follow symlink", e); //$NON-NLS-1$
}

if (path == null) {
return null;
}

// Sometimes users put in the path to the Dart executable directly, instead of
// the directory of the installation. Here we use the parent first (which should
// be /bin)
if (path.endsWith("dart") && !Files.isDirectory(path)) { //$NON-NLS-1$
path = path.getParent();
}
// Sometimes users put in the path when it still contains the /bin portion.
// Since we only want the root of the Dart SDK installation we use the parent if
// /bin was supplied.
if (path.endsWith("bin")) {//$NON-NLS-1$
path = path.getParent();
}

return path;
} else {
return null;
Expand Down
@@ -1,14 +1,26 @@
package org.eclipse.dartboard.preference;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.eclipse.core.runtime.Platform;
import org.eclipse.dartboard.Messages;
import org.eclipse.jface.preference.DirectoryFieldEditor;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.widgets.Composite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DartSDKLocationFieldEditor extends DirectoryFieldEditor {

private static final Logger LOG = LoggerFactory.getLogger(DartSDKLocationFieldEditor.class);

public DartSDKLocationFieldEditor(String preferencesKey, String label, Composite parent) {
super(preferencesKey, label, parent);
setValidateStrategy(VALIDATE_ON_KEY_STROKE);
Expand All @@ -17,15 +29,85 @@ public DartSDKLocationFieldEditor(String preferencesKey, String label, Composite
@Override
protected boolean doCheckState() {
String location = getTextControl().getText();
File file = new File(location);
boolean isValid = file.exists();
boolean isValid = isValidDartSDK(location);
if (!isValid) {
setErrorMessage(Messages.Preference_SDKNotFound_Message);
showErrorMessage();
}
return isValid;
}

/**
* Checks if a given path is the root directory of a Dart SDK installation.
*
* Returns false if the path does not exist or the given location can not be
* converted to a {@link Path}.
*
* Similarly if the Path is not a directory, false is returned.
*
* If the location is a symbolic link but it can not be resolved, false is
* returned.
*
* If the process to test the version string returned by the Dart executable can
* not be executed, false is returned.
*
* Finally, if the returned version string does not start with "Dart VM
* version", false is returned.
*
* @param location - A {@link String} that should be checked to be a Dart SDK
* root directory.
* @return <code>false</code> if the location is not a Dart SDK root directory,
* <code>true</code> otherwise.
*/
@SuppressWarnings("nls")
private boolean isValidDartSDK(String location) {
boolean isWindows = Platform.OS_WIN32.equals(Platform.getOS());
Path path = null;
// On Windows if a certain wrong combination of characters are entered a
// InvalidPathException is thrown. In that case we can assume that the location
// entered is not a valid Dart SDK directory either.
try {
path = Paths.get(location).resolve("bin" + File.separator + (isWindows ? "dart.exe" : "dart"));
} catch (InvalidPathException e) {
return false;
}
// If the entered file doesn't exist, there is no need to run it
// Similarly if the file is a directory it can't be the dart executable
if (!Files.exists(path) || Files.isDirectory(path)) {
return false;
}
// Follow symbolic links
try {
path = path.toRealPath();
} catch (IOException e1) {
LOG.error("Couldn't follow symlink", e1);
return false;
}


String executablePath = path.toAbsolutePath().toString();

String[] commands;
if (isWindows) {
commands = new String[] { "cmd", "/c", executablePath, "--version" };
} else {
commands = new String[] { "/bin/bash", "-c", executablePath + " --version" };
}

ProcessBuilder processBuilder = new ProcessBuilder(commands);

processBuilder.redirectErrorStream(true);
String version = null;
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(processBuilder.start().getInputStream()))) {
version = reader.readLine();
} catch (IOException e) {
return false;
}

return version.startsWith("Dart VM version");
}

protected void addModifyListener(ModifyListener listener) {
getTextControl().addModifyListener(listener);
}
Expand Down

0 comments on commit 6bfd1d8

Please sign in to comment.