blob: cfe00d3c4f37b5abe6c33e85409eceb9dfde1a4c [file] [log] [blame]
package org.eclipse.dltk.launching;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.dltk.core.environment.IEnvironment;
import org.eclipse.dltk.core.environment.IExecutionEnvironment;
import org.eclipse.dltk.core.environment.IFileHandle;
import org.eclipse.osgi.util.NLS;
public class InterpreterSearcher {
private Set<IFileHandle> searchedDirs;
private List<IFileHandle> found;
private List<IInterpreterInstallType> types;
private String natureId;
private IInterpreterInstallType[] installTypes;
private Set<IFileHandle> ignore;
protected void searchFast(IProgressMonitor monitor,
IEnvironment environment, int depth) {
if (monitor.isCanceled()) {
return;
}
// Path variable
IExecutionEnvironment exeEnv = environment
.getAdapter(IExecutionEnvironment.class);
if (exeEnv == null)
return;
monitor.subTask(Messages.InterpreterSearcher_0);
Map<String, String> env = exeEnv.getEnvironmentVariables(true);
if (env == null) {
return;
}
String path = null;
for (final String name : env.keySet()) {
if (name.equalsIgnoreCase("path")) { //$NON-NLS-1$
path = env.get(name);
break;
}
}
if (path == null) {
return;
}
// Folder list
final String separator = environment.getPathsSeparator();
final List<IPath> folders = new ArrayList<>();
String[] res = path.split(separator);
for (int i = 0; i < res.length; i++) {
folders.add(Path.fromOSString(res[i]));
}
monitor.beginTask(Messages.InterpreterSearcher_1, folders.size());
for (final IPath folder : folders) {
IFileHandle f = environment.getFile(folder);
if (f.isDirectory()) {
search(f, monitor, depth);
}
monitor.worked(1);
}
monitor.done();
}
/**
* Searches the specified directory recursively for installed Interpreters,
* adding each detected Interpreter to the <code>found</code> list. Any
* directories specified in the <code>ignore</code> are not traversed.
*
* @param directory
* @param found
* @param types
* @param ignore
* @param depth
* deepness of search. -1 if infinite.
*/
protected void search(IFileHandle directory, IProgressMonitor monitor,
int depth) {
if (depth == 0) {
return;
}
if (monitor.isCanceled()) {
return;
}
if (!searchedDirs.add(directory)) {
return;
}
IFileHandle[] files = directory.getChildren();
if (files == null) {
return;
}
List<IFileHandle> subDirs = new ArrayList<>();
for (int i = 0; i < files.length; i++) {
if (monitor.isCanceled()) {
return;
}
final IFileHandle file = files[i];
monitor.subTask(NLS.bind(
Messages.InterpreterSearcher_foundSearching,
Integer.valueOf(found.size()), file.getCanonicalPath()));
// Check if file is a symlink
if (file.isDirectory() && file.isSymlink()) {
continue;
}
if (!ignore.contains(file)) {
boolean validLocation = false;
// Take the first Interpreter install type that claims the
// location as a
// valid Interpreter install. Interpreter install types should
// be smart enough to not
// claim another type's Interpreter, but just in case...
for (int j = 0; j < installTypes.length; j++) {
if (monitor.isCanceled()) {
return;
}
final IInterpreterInstallType installType = installTypes[j];
IStatus status = installType.validatePossiblyName(file);
if (status.isOK()) {
found.add(file);
types.add(installType);
validLocation = true;
break;
}
}
if (file.isDirectory() && !validLocation) {
subDirs.add(file);
}
}
}
if (!subDirs.isEmpty()) {
for (IFileHandle subDir : subDirs) {
search(subDir, monitor, depth - 1);
}
}
}
public InterpreterSearcher() {
this.searchedDirs = new HashSet<>();
this.found = new ArrayList<>();
this.types = new ArrayList<>();
}
public void search(IEnvironment environment, String natureId,
Set<IFileHandle> ignore, int depth, IProgressMonitor monitor) {
if (natureId == null) {
throw new IllegalArgumentException();
}
this.found.clear();
this.types.clear();
this.searchedDirs.clear();
this.natureId = natureId;
this.installTypes = ScriptRuntime.getInterpreterInstallTypes(natureId);
this.ignore = ignore == null ? Collections.<IFileHandle> emptySet()
: ignore;
searchFast(monitor == null ? new NullProgressMonitor() : monitor,
environment, depth);
}
public boolean hasResults() {
return !found.isEmpty();
}
public IFileHandle[] getFoundFiles() {
return found.toArray(new IFileHandle[found.size()]);
}
public IInterpreterInstallType[] getFoundInstallTypes() {
return types.toArray(new IInterpreterInstallType[types.size()]);
}
}