| /******************************************************************************* |
| * 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; |
| } |
| } |