blob: 314535eec3b65addfc50b4f334841a45fe53513f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
package org.eclipse.dltk.tcl.internal.launching;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.environment.IDeployment;
import org.eclipse.dltk.core.environment.IEnvironment;
import org.eclipse.dltk.core.environment.IExecutionEnvironment;
import org.eclipse.dltk.core.environment.IFileHandle;
import org.eclipse.dltk.internal.launching.AbstractInterpreterInstallType;
import org.eclipse.dltk.internal.launching.DLTKLaunchingPlugin;
import org.eclipse.dltk.internal.launching.InterpreterMessages;
import org.eclipse.dltk.launching.EnvironmentVariable;
import org.eclipse.dltk.launching.IInterpreterInstall;
import org.eclipse.dltk.launching.InterpreterConfig;
import org.eclipse.dltk.launching.LibraryLocation;
import org.eclipse.dltk.launching.ScriptLaunchUtil;
import org.eclipse.dltk.tcl.core.TclLibpathUtils;
import org.eclipse.dltk.tcl.core.TclNature;
import org.eclipse.dltk.tcl.core.TclPackagesManager;
import org.eclipse.dltk.tcl.core.TclPlugin;
import org.eclipse.dltk.tcl.core.packages.TclInterpreterInfo;
import org.eclipse.dltk.tcl.core.packages.TclPackagesFactory;
import org.eclipse.dltk.tcl.internal.core.packages.ProcessOutputCollector;
import org.eclipse.dltk.tcl.launching.TclLaunchingPlugin;
import org.osgi.framework.Bundle;
public class GenericTclInstallType extends AbstractInterpreterInstallType {
private static final String INSTALL_TYPE_NAME = "Generic Tcl";
/**
* @since 1.1
*/
public static final String TYPE_ID = "org.eclipse.dltk.internal.debug.ui.launcher.GenericTclInstallType";
private static final String[] INTERPRETER_NAMES = { "tclsh", "tclsh84", "tclsh8.4", "tclsh85", "tclsh8.5",
"tclsh8.6",
"wish", "wish84", "wish85", "wish86", "wish8.4", "wish85", "wish8.5", "wish8.6",
"vtk",
"expect",
"base-tcl-linux", "base-tk-linux",
"base-tcl-thread", "base-tk-thread", "base-tcl8.5-thread", "base-tcl8.6-thread", "base-tk8.5-thread",
"base-tk8.6-thread" };
@Override
public String getNatureId() {
return TclNature.NATURE_ID;
}
@Override
public String getName() {
return INSTALL_TYPE_NAME;
}
@Override
protected String getPluginId() {
return TclLaunchingPlugin.PLUGIN_ID;
}
@Override
protected String[] getPossibleInterpreterNames() {
return INTERPRETER_NAMES;
}
@Override
protected IInterpreterInstall doCreateInterpreterInstall(String id) {
return new GenericTclInstall(this, id);
}
@Override
protected void filterEnvironment(Map<String, String> environment) {
// make sure that $auto_path is clean
environment.remove("TCLLIBPATH");
// block wish from showing window under linux
environment.remove("DISPLAY");
}
@Override
public IStatus validateInstallLocation(IFileHandle installLocation, EnvironmentVariable[] variables,
LibraryLocation[] libraries, IProgressMonitor monitor) {
/* Progress monitoring */monitor.beginTask("Validate Tcl interpreter", 100);
try {
if (!installLocation.exists() || !installLocation.isFile()) {
return createStatus(IStatus.ERROR, InterpreterMessages.errNonExistentOrInvalidInstallLocation, null);
}
IEnvironment environment = installLocation.getEnvironment();
IExecutionEnvironment executionEnvironment = environment.getAdapter(IExecutionEnvironment.class);
/* Progress monitoring */monitor.subTask("Deploy validation script");
IDeployment deployment = executionEnvironment.createDeployment();
if (deployment == null) {
// happens if RSE is not initialized yet or no connection
// established
return createStatus(IStatus.ERROR,
"Failed to deploy validation script to host:" + environment.getName(), null);
}
List<String> output = null;
Bundle bundle = TclPlugin.getDefault().getBundle();
try {
IFileHandle builderFile = deployment.getFile(deployment.add(bundle, "scripts/dltk.tcl"));
/* Progress monitoring */monitor.worked(10);
InterpreterConfig config = ScriptLaunchUtil.createInterpreterConfig(executionEnvironment, builderFile,
builderFile.getParent());
config.addScriptArg("get-pkgs");
// Configure environment variables
final Map<String, String> envVars = new HashMap<>();
Map<String, String> envVars2 = executionEnvironment.getEnvironmentVariables(false);
if (envVars2 != null) {
envVars.putAll(envVars2);
}
config.addEnvVars(envVars);
config.removeEnvVar("DISPLAY"); //$NON-NLS-1$
TclLibpathUtils.addTclLibPath(config, libraries, environment);
/* Progress monitoring */monitor.subTask("Running validation script");
String[] cmdLine = config.renderCommandLine(executionEnvironment.getEnvironment(),
installLocation.toOSString());
String[] environmentAsStrings = config.getEnvironmentAsStringsIncluding(variables);
IPath workingDirectoryPath = config.getWorkingDirectoryPath();
if (DLTKLaunchingPlugin.TRACE_EXECUTION) {
ScriptLaunchUtil.traceExecution("runScript with interpreter", cmdLine, //$NON-NLS-1$
environmentAsStrings);
}
final Process process = executionEnvironment.exec(cmdLine, workingDirectoryPath, environmentAsStrings);
/* Progress monitoring */monitor.worked(10);
SubProgressMonitor sm = new SubProgressMonitor(monitor, 70);
sm.beginTask("Running validation script", IProgressMonitor.UNKNOWN);
sm.done();
output = ProcessOutputCollector.execute(process, sm);
int exitValue = 0;
try {
exitValue = process.exitValue();
} catch (IllegalThreadStateException e) {
exitValue = -1;
}
if (exitValue != 0) {
return createStatus(IStatus.ERROR, "Interpreter return abnormal exit code:" + exitValue, null);
}
} catch (IOException e1) {
if (DLTKCore.DEBUG) {
e1.printStackTrace();
}
return null;
} catch (CoreException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
return null;
} finally {
deployment.dispose();
}
if (output == null) {
return createStatus(IStatus.ERROR, InterpreterMessages.errNoInterpreterExecutablesFound, null);
}
boolean correct = output.contains(TclPackagesManager.END_OF_STREAM);
if (correct) {
monitor.subTask("Processing validation result");
// Parse list of packages from output
// Generate fake interpreter install
TclInterpreterInfo info = TclPackagesFactory.eINSTANCE.createTclInterpreterInfo();
TclPackagesManager.fillPackagesFromContent(output, info);
monitor.worked(10);
return new StatusWithPackages(info);
} else {
return createStatus(IStatus.ERROR, InterpreterMessages.errNoInterpreterExecutablesFound, null);
}
} finally {
monitor.done();
}
}
@Override
protected ILookupRunnable createLookupRunnable(final IFileHandle installLocation,
final List<LibraryLocation> locations, final EnvironmentVariable[] variables) {
return monitor -> {
// This retrieval could not receive paths in some cases.
// String result = retrivePaths(installLocation, locations,
// monitor, createPathFile(), variables);
// This is safe retrieval
// String[] autoPath = DLTKTclHelper.getDefaultPath(
// installLocation, variables);
// IEnvironment env = installLocation.getEnvironment();
// if (autoPath != null) {
// for (int i = 0; i < autoPath.length; i++) {
// Path libraryPath = new Path(autoPath[i]);
// IFileHandle file = env.getFile(libraryPath);
// if (file.exists()) {
// locations.add(new LibraryLocation(libraryPath));
// }
// }
// }
};
}
@Override
protected String[] parsePaths(String res) {
ArrayList<String> paths = new ArrayList<>();
String subs = null;
int index = 0;
String result = res;
if (result.startsWith(DLTK_PATH_PREFIX)) {
result = result.substring(DLTK_PATH_PREFIX.length());
}
while (index < result.length()) {
// skip whitespaces
while (index < result.length() && Character.isWhitespace(result.charAt(index)))
index++;
if (index == result.length())
break;
if (result.charAt(index) == '{') {
int start = index;
while (index < result.length() && result.charAt(index) != '}')
index++;
if (index == result.length())
break;
subs = result.substring(start + 1, index);
} else {
int start = index;
while (index < result.length() && result.charAt(index) != ' ')
index++;
subs = result.substring(start, index);
}
paths.add(subs);
index++;
}
return paths.toArray(new String[paths.size()]);
}
@Override
protected ILog getLog() {
return TclLaunchingPlugin.getDefault().getLog();
}
@Override
protected IPath createPathFile(IDeployment deployment) throws IOException {
return null;
}
}