/*******************************************************************************
* Copyright (c) 2005, 2016 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.launching;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.Launch;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IScriptProject;
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.DLTKLaunchingPlugin;
import org.eclipse.dltk.internal.launching.EnvironmentResolver;
import org.eclipse.dltk.launching.ScriptRuntime.DefaultInterpreterEntry;
import org.osgi.framework.Bundle;
public class ScriptLaunchUtil {
// Creating of InterpreterConfig
public static InterpreterConfig createInterpreterConfig(
IExecutionEnvironment exeEnv, IFileHandle scriptFile,
IFileHandle workingDirectory) {
return createInterpreterConfig(exeEnv, scriptFile, workingDirectory,
null);
}
public static InterpreterConfig createInterpreterConfig(
IExecutionEnvironment exeEnv, IFileHandle scriptFile,
IFileHandle workingDirectory, EnvironmentVariable[] env) {
IPath workingDirectoryPath = null;
if (workingDirectory != null) {
workingDirectoryPath = new Path(workingDirectory.toOSString());
}
InterpreterConfig config = new InterpreterConfig(
scriptFile.getEnvironment(), new Path(scriptFile.toOSString()),
workingDirectoryPath);
Map<String, String> envVars = exeEnv.getEnvironmentVariables(false);
if (envVars != null) {
config.addEnvVars(envVars);
EnvironmentVariable[] resVars = EnvironmentResolver.resolve(envVars,
env);
if (resVars != null) {
for (int i = 0; i < resVars.length; i++) {
config.addEnvVar(resVars[i].getName(),
resVars[i].getValue());
}
}
}
return config;
}
// Useful run methods
public static Process runScriptWithInterpreter(IExecutionEnvironment exeEnv,
String interpreter, InterpreterConfig config) throws CoreException {
String[] cmdLine = config.renderCommandLine(exeEnv.getEnvironment(),
interpreter);
String[] environmentAsStrings = config.getEnvironmentAsStrings();
IPath workingDirectoryPath = config.getWorkingDirectoryPath();
if (DLTKLaunchingPlugin.TRACE_EXECUTION) {
traceExecution("runScript with interpreter", cmdLine, //$NON-NLS-1$
environmentAsStrings);
}
return exeEnv.exec(cmdLine, workingDirectoryPath, environmentAsStrings);
}
/**
* @since 2.0
*/
public static void traceExecution(String processLabel,
String[] cmdLineLabel, String[] environment) {
StringBuffer sb = new StringBuffer();
sb.append("-----------------------------------------------\n"); //$NON-NLS-1$
sb.append("Running ").append(processLabel).append('\n'); //$NON-NLS-1$
// sb.append("Command line: ").append(cmdLineLabel).append('\n');
sb.append("Command line: "); //$NON-NLS-1$
for (int i = 0; i < cmdLineLabel.length; i++) {
sb.append(" " + cmdLineLabel[i]); //$NON-NLS-1$
}
sb.append("\n"); //$NON-NLS-1$
sb.append("Environment:\n"); //$NON-NLS-1$
for (int i = 0; i < environment.length; i++) {
sb.append('\t').append(environment[i]).append('\n');
}
sb.append("-----------------------------------------------\n"); //$NON-NLS-1$
System.out.println(sb);
}
public static Process runScriptWithInterpreter(IExecutionEnvironment exeEnv,
String interpreter, IFileHandle scriptFile,
IFileHandle workingDirectory, String[] interpreterArgs,
String[] scriptArgs, EnvironmentVariable[] environment)
throws CoreException {
InterpreterConfig config = createInterpreterConfig(exeEnv, scriptFile,
workingDirectory, environment);
if (scriptArgs != null) {
config.addScriptArgs(scriptArgs);
}
if (interpreterArgs != null) {
config.addInterpreterArgs(interpreterArgs);
}
return runScriptWithInterpreter(exeEnv, interpreter, config);
}
public static IInterpreterInstall getDefaultInterpreterInstall(
String natureId, String environment) {
return ScriptRuntime.getDefaultInterpreterInstall(
new DefaultInterpreterEntry(natureId, environment));
}
public static IInterpreterInstall getProjectInterpreterInstall(
IScriptProject project) throws CoreException {
return ScriptRuntime.getInterpreterInstall(project);
}
// General run method
public static ILaunch runScript(IInterpreterInstall install,
InterpreterConfig config, IProgressMonitor monitor)
throws CoreException {
if (install == null) {
return null;
}
ILaunch launch = new Launch(null, ILaunchManager.RUN_MODE, null);
// will use 'instance scoped' interpreter here
IInterpreterRunner runner = install
.getInterpreterRunner(launch.getLaunchMode());
runner.run(config, launch, monitor);
return launch;
}
// Run by interpreter form project
public static ILaunch runScript(IScriptProject project,
InterpreterConfig config, IProgressMonitor monitor)
throws CoreException {
return runScript(getProjectInterpreterInstall(project), config,
monitor);
}
// Run by default interpreter
public static ILaunch runScript(String natureId, String environment,
InterpreterConfig config, IProgressMonitor monitor)
throws CoreException {
IInterpreterInstall install = getDefaultInterpreterInstall(natureId,
environment);
EnvironmentVariable[] variables = EnvironmentResolver.resolve(
config.getEnvVars(), install.getEnvironmentVariables());
if (variables != null) {
for (int i = 0; i < variables.length; i++) {
config.addEnvVar(variables[i].getName(),
variables[i].getValue());
}
}
return runScript(install, config, monitor);
}
// Script file
public static ILaunch runScript(String natureId, IFileHandle scriptFile,
IFileHandle workingDirectory, String[] interpreterArgs,
String[] scriptArgs, IProgressMonitor monitor)
throws CoreException {
IEnvironment environment = scriptFile.getEnvironment();
IExecutionEnvironment execEnvironment = environment
.getAdapter(IExecutionEnvironment.class);
InterpreterConfig config = createInterpreterConfig(execEnvironment,
scriptFile, workingDirectory);
if (interpreterArgs != null) {
config.addInterpreterArgs(interpreterArgs);
}
if (scriptArgs != null) {
config.addScriptArgs(scriptArgs);
}
return runScript(natureId, environment.getId(), config, monitor);
}
/**
* @since 2.0
*/
public static ILaunch runScript(IInterpreterInstall install,
IFileHandle scriptFile, IFileHandle workingDirectory,
String[] interpreterArgs, String[] scriptArgs,
IProgressMonitor monitor) throws CoreException {
IEnvironment environment = scriptFile.getEnvironment();
IExecutionEnvironment execEnvironment = environment
.getAdapter(IExecutionEnvironment.class);
InterpreterConfig config = createInterpreterConfig(execEnvironment,
scriptFile, workingDirectory);
if (interpreterArgs != null) {
config.addInterpreterArgs(interpreterArgs);
}
if (scriptArgs != null) {
config.addScriptArgs(scriptArgs);
}
EnvironmentVariable[] variables = EnvironmentResolver.resolve(
config.getEnvVars(), install.getEnvironmentVariables());
if (variables != null) {
for (int i = 0; i < variables.length; i++) {
config.addEnvVar(variables[i].getName(),
variables[i].getValue());
}
}
return runScript(install, config, monitor);
}
/**
* @since 2.0
*/
public static class ErrorStreamReaderThread extends Thread {
final InputStream stream;
/**
* @param stream
*/
public ErrorStreamReaderThread(InputStream stream) {
this.stream = stream;
}
@Override
public void run() {
byte[] buffer = new byte[256];
try {
while (stream.read(buffer) != -1) {
// ignore
}
} catch (IOException e) {
// ignore
}
}
}
/**
* @since 2.0
*/
public static class OutputStreamReaderThread extends Thread {
final InputStream stream;
final StringBuffer output;
final IProgressMonitor monitor;
public OutputStreamReaderThread(InputStream stream, StringBuffer output,
IProgressMonitor monitor) {
this.stream = stream;
this.output = output;
this.monitor = monitor;
}
@Override
public void run() {
BufferedReader input = null;
try {
input = new BufferedReader(new InputStreamReader(stream));
String line;
while ((line = input.readLine()) != null) {
output.append(line);
output.append("\n"); //$NON-NLS-1$
monitor.worked(1);
}
} catch (IOException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
}
}
}
}
/**
* Read content from specified stream.
*
* @return Return empty string in error.
*/
public static String runEmbeddedScriptReadContent(
IExecutionEnvironment exeEnv, String scriptPath, Bundle bundle,
IFileHandle installLocations, final IProgressMonitor monitor) {
IDeployment deployment = exeEnv.createDeployment();
if (deployment == null) {
// happens if RSE is not initialized yet or no connection
// established
return null;
}
try {
IFileHandle builderFile = deployment
.getFile(deployment.add(bundle, scriptPath));
InterpreterConfig config = ScriptLaunchUtil.createInterpreterConfig(
exeEnv, builderFile, builderFile.getParent());
config.removeEnvVar("DISPLAY"); //$NON-NLS-1$
final StringBuffer source = new StringBuffer();
final Process process = ScriptLaunchUtil.runScriptWithInterpreter(
exeEnv, installLocations.toOSString(), config);
try {
process.getOutputStream().close();
new ErrorStreamReaderThread(process.getErrorStream()).start();
new OutputStreamReaderThread(process.getInputStream(), source,
monitor).start();
final Thread waitThread = new Thread() {
@Override
public void run() {
try {
process.waitFor();
} catch (InterruptedException e) {
// ignore
}
}
};
try {
waitThread.start();
waitThread.join(10000);
} catch (InterruptedException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
} finally {
process.destroy();
}
return source.toString();
} catch (IOException e1) {
if (DLTKCore.DEBUG) {
e1.printStackTrace();
}
return null;
} catch (CoreException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
return null;
} finally {
deployment.dispose();
}
}
}