| package org.eclipse.dltk.core.internal.rse; |
| |
| import java.io.BufferedReader; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.net.URI; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Random; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| 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.IExecutionLogger; |
| import org.eclipse.dltk.core.internal.rse.perfomance.RSEPerfomanceStatistics; |
| import org.eclipse.dltk.internal.launching.execution.EFSDeployment; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.rse.core.model.IHost; |
| import org.eclipse.rse.core.subsystems.ISubSystem; |
| import org.eclipse.rse.internal.efs.RSEFileSystem; |
| import org.eclipse.rse.services.clientserver.messages.SystemMessageException; |
| import org.eclipse.rse.services.shells.IHostShell; |
| import org.eclipse.rse.services.shells.IShellService; |
| import org.eclipse.rse.subsystems.shells.core.subsystems.servicesubsystem.IShellServiceSubSystem; |
| |
| public class RSEExecEnvironment implements IExecutionEnvironment { |
| |
| private static final String SHELL_PATH = "exec /bin/sh"; //$NON-NLS-1$ |
| |
| private static final String CMD_SEPARATOR = ";"; //$NON-NLS-1$ |
| private static final String EXPORT_CMD = ";export "; //$NON-NLS-1$ |
| private final static String EXIT_CMD = "exit"; //$NON-NLS-1$ |
| private static final String SET_CMD = "set"; //$NON-NLS-1$ |
| private static final String BACKSLASH = " \\"; //$NON-NLS-1$ |
| |
| private final RSEEnvironment environment; |
| private static int counter = -1; |
| |
| private static final Map hostToEnvironment = new HashMap(); |
| |
| public RSEExecEnvironment(RSEEnvironment env) { |
| this.environment = env; |
| } |
| |
| public IDeployment createDeployment() { |
| if (RSEPerfomanceStatistics.PERFOMANCE_TRACING) { |
| RSEPerfomanceStatistics |
| .inc(RSEPerfomanceStatistics.DEPLOYMENTS_CREATED); |
| } |
| try { |
| String tmpDir = getTempDir(); |
| if (tmpDir != null) { |
| String rootPath = tmpDir + environment.getSeparator() |
| + getTempName("dltk", ".tmp"); //$NON-NLS-1$ //$NON-NLS-2$ |
| URI rootUri = createRemoteURI(environment.getHost(), rootPath); |
| return new EFSDeployment(environment, rootUri); |
| } |
| } catch (CoreException e) { |
| if (DLTKCore.DEBUG) |
| e.printStackTrace(); |
| } |
| |
| return null; |
| } |
| |
| private URI createRemoteURI(IHost host, String rootPath) { |
| return RSEFileSystem.getURIFor(host.getHostName(), rootPath); |
| } |
| |
| private IShellServiceSubSystem getShellServiceSubSystem(IHost host) { |
| ISubSystem[] subsys = host.getSubSystems(); |
| for (int i = 0; i < subsys.length; i++) { |
| if (subsys[i] instanceof IShellServiceSubSystem) |
| return (IShellServiceSubSystem) subsys[i]; |
| } |
| return null; |
| } |
| |
| private String getTempName(String prefix, String suffix) { |
| if (counter == -1) { |
| counter = new Random().nextInt() & 0xffff; |
| } |
| counter++; |
| return prefix + Integer.toString(counter) + suffix; |
| } |
| |
| private String getTempDir() { |
| IHost host = environment.getHost(); |
| IShellServiceSubSystem system = getShellServiceSubSystem(host); |
| |
| if (system == null) { |
| DLTKRSEPlugin.logWarning(NLS.bind( |
| Messages.RSEExecEnvironment_hostNotFound, host.getName())); |
| return null; |
| } |
| |
| String tmpDir = null; |
| try { |
| system.connect(new NullProgressMonitor(), false); |
| |
| tmpDir = system.getConnectorService().getTempDirectory(); |
| if (tmpDir.length() == 0) { |
| tmpDir = "/tmp"; //$NON-NLS-1$ |
| } |
| |
| } catch (Exception e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| } |
| |
| return tmpDir; |
| } |
| |
| public Process exec(String[] cmdLine, IPath workingDir, String[] environment) |
| throws CoreException { |
| return exec(cmdLine, workingDir, environment, null); |
| } |
| |
| public Process exec(String[] cmdLine, IPath workingDir, |
| String[] environment, IExecutionLogger logger) throws CoreException { |
| if (RSEPerfomanceStatistics.PERFOMANCE_TRACING) { |
| RSEPerfomanceStatistics |
| .inc(RSEPerfomanceStatistics.EXECUTION_COUNT); |
| } |
| long start = System.currentTimeMillis(); |
| IShellServiceSubSystem shell = getShellServiceSubSystem(this.environment |
| .getHost()); |
| try { |
| shell.connect(null, false); |
| } catch (Exception e) { |
| if (DLTKCore.DEBUG) { |
| e.printStackTrace(); |
| } |
| return null; |
| } |
| |
| if (!shell.isConnected()) { |
| return null; |
| } |
| IShellService shellService = shell.getShellService(); |
| IHostShell hostShell = null; |
| String workingDirectory = null; |
| if (workingDir != null) { |
| workingDirectory = this.environment.convertPathToString(workingDir); |
| } else { |
| workingDirectory = "/"; //$NON-NLS-1$ |
| } |
| try { |
| hostShell = shellService.runCommand(workingDirectory, SHELL_PATH, |
| environment, new NullProgressMonitor()); |
| } catch (SystemMessageException e1) { |
| DLTKRSEPlugin.log(e1); |
| return null; |
| } |
| |
| // Sometimes environment variables aren't set, so use export. |
| if (environment != null) { |
| hostShell.writeToShell(SHELL_PATH); |
| // TODO: Skip environment variables what is already in shell. |
| for (int i = 0; i < environment.length; i++) { |
| hostShell.writeToShell(toShellArguments(environment[i]) |
| + EXPORT_CMD + extractName(environment[i])); |
| } |
| } |
| final String pattern = "DLTK_INITIAL_PREFIX_EXECUTION_STRING:" //$NON-NLS-1$ |
| + String.valueOf(System.currentTimeMillis()); |
| final String echoPattern = "echo \"" + pattern + "\""; //$NON-NLS-1$ //$NON-NLS-2$ |
| hostShell.writeToShell(echoPattern + CMD_SEPARATOR + BACKSLASH); |
| hostShell.writeToShell(buildCommand(cmdLine) + CMD_SEPARATOR |
| + BACKSLASH); |
| hostShell.writeToShell(echoPattern + CMD_SEPARATOR + EXIT_CMD); |
| Process p = null; |
| try { |
| p = new MyHostShellProcessAdapter(hostShell, pattern, logger); |
| } catch (Exception e) { |
| if (p != null) { |
| p.destroy(); |
| } |
| throw new RuntimeException("Failed to run remote command"); //$NON-NLS-1$ |
| } |
| if (RSEPerfomanceStatistics.PERFOMANCE_TRACING) { |
| final long end = System.currentTimeMillis(); |
| RSEPerfomanceStatistics.inc(RSEPerfomanceStatistics.EXECUTION_TIME, |
| (end - start)); |
| } |
| return p; |
| } |
| |
| /** |
| * @param environmentEntry |
| * @return |
| */ |
| private String extractName(String environmentEntry) { |
| final int pos = environmentEntry.indexOf('='); |
| return pos > 0 ? environmentEntry.substring(0, pos) : environmentEntry; |
| } |
| |
| private String toShellArguments(String cmd) { |
| String replaceAll = cmd.replaceAll(" ", "\\\\ "); //$NON-NLS-1$ //$NON-NLS-2$ |
| return replaceAll; |
| } |
| |
| // private String createWorkingDir(IPath workingDir) { |
| // if (workingDir == null) |
| // return "."; //$NON-NLS-1$ |
| // return workingDir.toPortableString(); |
| // } |
| |
| private String buildCommand(String[] cmdLine) { |
| StringBuffer cmd = new StringBuffer(); |
| for (int i = 0; i < cmdLine.length; i++) { |
| if (i != 0) { |
| cmd.append(" "); //$NON-NLS-1$ |
| } |
| cmd.append(cmdLine[i]); |
| } |
| return cmd.toString(); |
| } |
| |
| public Map getEnvironmentVariables(boolean realyNeed) { |
| if (!realyNeed) { |
| return new HashMap(); |
| } |
| final long start = System.currentTimeMillis(); |
| synchronized (hostToEnvironment) { |
| final Map result = (Map) hostToEnvironment.get(environment |
| .getHost()); |
| if (result != null) { |
| return new HashMap(result); |
| } |
| } |
| final Map result = new HashMap(); |
| try { |
| Process process = this.exec(new String[] { SET_CMD }, Path.EMPTY, |
| null); |
| if (process != null) { |
| final BufferedReader input = new BufferedReader( |
| new InputStreamReader(process.getInputStream())); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| while (true) { |
| String line = input.readLine(); |
| if (line == null) { |
| break; |
| } |
| line = line.trim(); |
| int pos = line.indexOf("="); //$NON-NLS-1$ |
| if (pos != -1) { |
| String varName = line.substring(0, pos); |
| String varValue = line.substring(pos + 1); |
| result.put(varName, varValue); |
| } |
| } |
| } catch (IOException e) { |
| DLTKRSEPlugin.log(e); |
| } |
| } |
| }); |
| t.start(); |
| try { |
| t.join(25000);// No more than 25 seconds |
| } catch (InterruptedException e) { |
| DLTKRSEPlugin.log(e); |
| } |
| process.destroy(); |
| } |
| } catch (CoreException e) { |
| DLTKRSEPlugin.log(e); |
| } |
| if (!result.isEmpty()) { |
| synchronized (hostToEnvironment) { |
| hostToEnvironment.put(this.environment.getHost(), Collections |
| .unmodifiableMap(result)); |
| } |
| } |
| if (RSEPerfomanceStatistics.PERFOMANCE_TRACING) { |
| final long end = System.currentTimeMillis(); |
| RSEPerfomanceStatistics |
| .inc(RSEPerfomanceStatistics.ENVIRONMENT_RECEIVE_COUNT); |
| RSEPerfomanceStatistics.inc( |
| RSEPerfomanceStatistics.ENVIRONMENT_RECEIVE_TIME, |
| (end - start)); |
| } |
| return result; |
| } |
| |
| public IEnvironment getEnvironment() { |
| return environment; |
| } |
| |
| public boolean isValidExecutableAndEquals(String possibleName, IPath path) { |
| if (environment.getHost().getSystemType().isWindows()) { |
| possibleName = possibleName.toLowerCase(); |
| String fName = path.removeFileExtension().toString().toLowerCase(); |
| String ext = path.getFileExtension(); |
| if (possibleName.equals(fName) |
| && ("exe".equalsIgnoreCase(ext) || "bat".equalsIgnoreCase(ext))) { //$NON-NLS-1$ //$NON-NLS-2$ |
| return true; |
| } |
| } else { |
| String fName = path.lastSegment(); |
| if (fName.equals(possibleName)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| } |