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