diff options
author | Uwe Stieber | 2013-08-28 08:37:51 +0000 |
---|---|---|
committer | Uwe Stieber | 2013-08-28 08:38:52 +0000 |
commit | 03d8f17370653cdec39dba42526cdd3f7f64299a (patch) | |
tree | 4cf0b7d895ef50ea924e41a3c4b83f38e3dfcf44 /target_explorer | |
parent | 4f5d7e82c55f29711d40e1dabfe065754f4aef26 (diff) | |
download | org.eclipse.tcf-03d8f17370653cdec39dba42526cdd3f7f64299a.tar.gz org.eclipse.tcf-03d8f17370653cdec39dba42526cdd3f7f64299a.tar.xz org.eclipse.tcf-03d8f17370653cdec39dba42526cdd3f7f64299a.zip |
Target Explorer: Extend value add launcher to allow to set a specific environment for the value add
Diffstat (limited to 'target_explorer')
3 files changed, 273 insertions, 217 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/utils/Env.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/utils/Env.java new file mode 100644 index 000000000..babcfc2c2 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime/src/org/eclipse/tcf/te/runtime/utils/Env.java @@ -0,0 +1,249 @@ +/******************************************************************************* + * Copyright (c) 2013 Wind River Systems, Inc. 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 + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.te.runtime.utils; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Platform; +import org.eclipse.osgi.service.environment.Constants; +import org.eclipse.tcf.te.runtime.activator.CoreBundleActivator; + +/** + * Environment handling utility methods. + */ +public class Env { + + // Reference to the monitor to lock if determining the native environment + private final static Object ENV_GET_MONITOR = new Object(); + + // Reference to the native environment once retrieved + private static Map<String, String> nativeEnvironment = null; + // Reference to the native environment with the case of the variable names preserved + private static Map<String, String> nativeEnvironmentCasePreserved = null; + + /** + * Returns the merged environment of the native environment and the passed + * in environment. Passed in variables will overwrite the native environment + * if the same variables are set there. + * <p> + * For use with terminals, the parameter <code>terminal</code> should be set to + * <code>true</code>. In this case, the method will assure that the <code>TERM</code> + * environment variable is always set to <code>ANSI</code> and is not overwritten + * by the passed in environment. + * + * @param envp The environment to set on top of the native environment or <code>null</code>. + * @param terminal <code>True</code> if used with an terminal, <code>false</code> otherwise. + * + * @return The merged environment. + */ + public static String[] getEnvironment(String[] envp, boolean terminal) { + Map<String, String> env = getNativeEnvironment(); + + if (terminal) env.put("TERM", "ansi"); //$NON-NLS-1$ //$NON-NLS-2$ + + Iterator<Map.Entry<String, String>> iter = env.entrySet().iterator(); + List<String> strings = new ArrayList<String>(env.size()); + StringBuffer buffer = null; + while (iter.hasNext()) { + Map.Entry<String, String> entry = iter.next(); + buffer = new StringBuffer(entry.getKey()); + buffer.append('=').append(entry.getValue()); + strings.add(buffer.toString()); + } + + // if "local" environment is provided - append + if (envp != null) { + // add provided + for (int i = 0; i < envp.length; i++) { + String envpPart = envp[i]; + // don't override TERM + String[] parts = envpPart.split("=");//$NON-NLS-1$ + if (!terminal || !parts[0].trim().equals("TERM")) {//$NON-NLS-1$ + strings.add(envpPart); + } + } + } + + return strings.toArray(new String[strings.size()]); + } + + /** + * Determine the native environment, but returns all environment variable + * names in upper case. + * + * @return The native environment with upper case variable names, or an empty map. + */ + private static Map<String, String> getNativeEnvironment() { + synchronized (ENV_GET_MONITOR) { + if (nativeEnvironment == null) { + Map<String, String> casePreserved = getNativeEnvironmentCasePreserved(); + if (Platform.getOS().equals(org.eclipse.osgi.service.environment.Constants.OS_WIN32)) { + nativeEnvironment = new HashMap<String, String>(); + Iterator<Map.Entry<String, String>> entries = casePreserved.entrySet().iterator(); + while (entries.hasNext()) { + Map.Entry<String, String> entry = entries.next(); + nativeEnvironment.put(entry.getKey().toUpperCase(), entry.getValue()); + } + } else { + nativeEnvironment = new HashMap<String, String>(casePreserved); + } + } + return new HashMap<String, String>(nativeEnvironment); + } + } + + /** + * Determine the native environment. + * + * @return The native environment, or an empty map. + */ + private static Map<String, String> getNativeEnvironmentCasePreserved() { + synchronized (ENV_GET_MONITOR) { + if (nativeEnvironmentCasePreserved == null) { + nativeEnvironmentCasePreserved= new HashMap<String, String>(); + cacheNativeEnvironment(nativeEnvironmentCasePreserved); + } + return new HashMap<String, String>(nativeEnvironmentCasePreserved); + } + } + + /** + * Query the native environment and store it to the specified cache. + * + * @param cache The environment cache. Must not be <code>null</code>. + */ + private static void cacheNativeEnvironment(Map<String, String> cache) { + Assert.isNotNull(cache); + + try { + String nativeCommand = null; + boolean isWin9xME = false; // see bug 50567 + String fileName = null; + if (Platform.getOS().equals(Constants.OS_WIN32)) { + String osName = System.getProperty("os.name"); //$NON-NLS-1$ + isWin9xME = osName != null && (osName.startsWith("Windows 9") || osName.startsWith("Windows ME")); //$NON-NLS-1$ //$NON-NLS-2$ + if (isWin9xME) { + // Win 95, 98, and ME + // SET might not return therefore we pipe into a file + IPath stateLocation = Platform.getStateLocation(CoreBundleActivator.getContext().getBundle()); + fileName = stateLocation.toOSString() + File.separator + "env.txt"; //$NON-NLS-1$ + nativeCommand = "command.com /C set > " + fileName; //$NON-NLS-1$ + } else { + // Win NT, 2K, XP + nativeCommand = "cmd.exe /C set"; //$NON-NLS-1$ + } + } else if (!Platform.getOS().equals(Constants.OS_UNKNOWN)) { + nativeCommand = "env"; //$NON-NLS-1$ + } + if (nativeCommand == null) { return; } + Process process = Runtime.getRuntime().exec(nativeCommand); + if (isWin9xME) { + // read piped data on Win 95, 98, and ME + Properties p = new Properties(); + File file = new File(fileName); + InputStream stream = null; + try { + stream = new BufferedInputStream(new FileInputStream(file)); + p.load(stream); + } finally { + if (stream != null) stream.close(); + } + if (!file.delete()) { + file.deleteOnExit(); // if delete() fails try again on VM close + } + for (Enumeration<Object> enumeration = p.keys(); enumeration.hasMoreElements();) { + // Win32's environment variables are case insensitive. Put everything + // to upper case so that (for example) the "PATH" variable will match + // "pAtH" correctly on Windows. + String key = (String)enumeration.nextElement(); + cache.put(key, (String)p.get(key)); + } + } else { + // read process directly on other platforms + // we need to parse out matching '{' and '}' for function declarations in .bash environments + // pattern is [function name]=() { and we must find the '}' on its own line with no trailing ';' + InputStream stream = process.getInputStream(); + InputStreamReader isreader = new InputStreamReader(stream); + BufferedReader reader = new BufferedReader(isreader); + try { + String line = reader.readLine(); + String key = null; + String value = null; + while (line != null) { + int func = line.indexOf("=()"); //$NON-NLS-1$ + if (func > 0) { + key = line.substring(0, func); + // scan until we find the closing '}' with no following chars + value = line.substring(func + 1); + while (line != null && !line.equals("}")) { //$NON-NLS-1$ + line = reader.readLine(); + if (line != null) { + value += line; + } + } + line = reader.readLine(); + } else { + int separator = line.indexOf('='); + if (separator > 0) { + key = line.substring(0, separator); + value = line.substring(separator + 1); + StringBuilder bufValue = new StringBuilder(value); + line = reader.readLine(); + if (line != null) { + // this line has a '=' read ahead to check next line for '=', might be broken on more + // than one line + separator = line.indexOf('='); + while (separator < 0) { + bufValue.append(line.trim()); + line = reader.readLine(); + if (line == null) { + // if next line read is the end of the file quit the loop + break; + } + separator = line.indexOf('='); + } + } + value = bufValue.toString(); + } + } + if (key != null) { + cache.put(key, value); + key = null; + value = null; + } else { + line = reader.readLine(); + } + } + } finally { + reader.close(); + } + } + } catch (IOException e) { + // Native environment-fetching code failed. + // This can easily happen and is not useful to log. + } + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/va/ValueAddLauncher.java b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/va/ValueAddLauncher.java index c886dfc55..2a43bbca8 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/va/ValueAddLauncher.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.tcf.core/src/org/eclipse/tcf/te/tcf/core/va/ValueAddLauncher.java @@ -22,6 +22,7 @@ import org.eclipse.core.runtime.Platform; import org.eclipse.osgi.util.NLS; import org.eclipse.tcf.te.runtime.processes.ProcessLauncher; import org.eclipse.tcf.te.runtime.processes.ProcessOutputReaderThread; +import org.eclipse.tcf.te.runtime.utils.Env; import org.eclipse.tcf.te.runtime.utils.Host; import org.eclipse.tcf.te.tcf.core.activator.CoreBundleActivator; import org.eclipse.tcf.te.tcf.core.interfaces.tracing.ITraceIds; @@ -136,8 +137,18 @@ public class ValueAddLauncher extends ProcessLauncher { 0, ITraceIds.TRACE_CHANNEL_MANAGER, IStatus.INFO, this); } + // Determine the environment + String[] envp = null; + + // Get the set of environment variables the launcher requires to set + String[] additional = getEnvironmentVariables(); + if (additional != null && additional.length > 0) { + // Get the native environment and merge the additional variables + envp = Env.getEnvironment(additional, false); + } + // Launch the value-add - process = Runtime.getRuntime().exec(command.toArray(new String[command.size()]), null, dir.toFile()); + process = Runtime.getRuntime().exec(command.toArray(new String[command.size()]), envp, dir.toFile()); // Launch the process output reader outputReader = new ProcessOutputReaderThread(path.lastSegment(), new InputStream[] { process.getInputStream() }); @@ -181,4 +192,14 @@ public class ValueAddLauncher extends ProcessLauncher { return port; } + /** + * Returns the set of environment variable which needs to be added to + * the native environment or overwritten in the native environment in + * order to launch the value add successfully. + * + * @return The set of environment variables or <code>null</code>. + */ + protected String[] getEnvironmentVariables() { + return null; + } } diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals.process/src/org/eclipse/tcf/te/ui/terminals/process/ProcessConnector.java b/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals.process/src/org/eclipse/tcf/te/ui/terminals/process/ProcessConnector.java index 28df4ec63..d0d665466 100644 --- a/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals.process/src/org/eclipse/tcf/te/ui/terminals/process/ProcessConnector.java +++ b/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals.process/src/org/eclipse/tcf/te/ui/terminals/process/ProcessConnector.java @@ -9,33 +9,21 @@ *******************************************************************************/ package org.eclipse.tcf.te.ui.terminals.process; -import java.io.BufferedInputStream; -import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.io.StreamTokenizer; import java.io.StringReader; import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; import java.util.List; -import java.util.Map; -import java.util.Properties; import org.eclipse.cdt.utils.pty.PTY; import org.eclipse.cdt.utils.spawner.ProcessFactory; import org.eclipse.core.runtime.Assert; -import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; -import org.eclipse.osgi.service.environment.Constants; import org.eclipse.osgi.util.NLS; import org.eclipse.tcf.te.runtime.services.interfaces.constants.ILineSeparatorConstants; +import org.eclipse.tcf.te.runtime.utils.Env; import org.eclipse.tcf.te.ui.terminals.process.activator.UIPlugin; import org.eclipse.tcf.te.ui.terminals.process.nls.Messages; import org.eclipse.tcf.te.ui.terminals.streams.AbstractStreamsConnector; @@ -159,7 +147,7 @@ public class ProcessConnector extends AbstractStreamsConnector { } // Execute the process - process = ProcessFactory.getFactory().exec(argv.toArray(new String[argv.size()]), getProcessEnvironment(envp), workingDir, pty); + process = ProcessFactory.getFactory().exec(argv.toArray(new String[argv.size()]), Env.getEnvironment(envp, true), workingDir, pty); } else { // No PTY -> just execute via the standard Java Runtime implementation. process = Runtime.getRuntime().exec(command.toString(), envp, workingDir); @@ -271,206 +259,4 @@ public class ProcessConnector extends AbstractStreamsConnector { } } - // ***** Process Environment Handling ***** - - // Reference to the monitor to lock if determining the native environment - private final static Object ENV_GET_MONITOR = new Object(); - - // Reference to the native environment once retrieved - private static Map<String, String> nativeEnvironment = null; - // Reference to the native environment with the case of the variable names preserved - private static Map<String, String> nativeEnvironmentCasePreserved = null; - - /** - * Returns the specific environment to set for the process to be launched. - * - * @return The process environment. - */ - private static String[] getProcessEnvironment(String[] envp) { - Map<String, String> env = getNativeEnvironment(); - - env.put("TERM", "ansi"); //$NON-NLS-1$ //$NON-NLS-2$ - - Iterator<Map.Entry<String, String>> iter = env.entrySet().iterator(); - List<String> strings = new ArrayList<String>(env.size()); - StringBuffer buffer = null; - while (iter.hasNext()) { - Map.Entry<String, String>entry = iter.next(); - buffer = new StringBuffer(entry.getKey()); - buffer.append('=').append(entry.getValue()); - strings.add(buffer.toString()); - } - - // if "local" environment is provided - append - if (envp!=null){ - // add provided - for (int i=0; i<envp.length; i++){ - String envpPart = envp[i]; - // dont override TERM - String[] parts=envpPart.split("=");//$NON-NLS-1$ - if (!parts[0].trim().equals("TERM")){//$NON-NLS-1$ - strings.add(envpPart); - } - } - } - - return strings.toArray(new String[strings.size()]); - } - - /** - * Determine the native environment, but returns all environment variable - * names in upper case. - * - * @return The native environment with upper case variable names, or an empty map. - */ - private static Map<String, String> getNativeEnvironment() { - synchronized (ENV_GET_MONITOR) { - if (nativeEnvironment == null) { - Map<String, String> casePreserved = getNativeEnvironmentCasePreserved(); - if (Platform.getOS().equals(org.eclipse.osgi.service.environment.Constants.OS_WIN32)) { - nativeEnvironment = new HashMap<String, String>(); - Iterator<Map.Entry<String, String>> entries = casePreserved.entrySet().iterator(); - while (entries.hasNext()) { - Map.Entry<String, String> entry = entries.next(); - nativeEnvironment.put(entry.getKey().toUpperCase(), entry.getValue()); - } - } else { - nativeEnvironment = new HashMap<String, String>(casePreserved); - } - } - return new HashMap<String, String>(nativeEnvironment); - } - } - - /** - * Determine the native environment. - * - * @return The native environment, or an empty map. - */ - private static Map<String, String> getNativeEnvironmentCasePreserved() { - synchronized (ENV_GET_MONITOR) { - if (nativeEnvironmentCasePreserved == null) { - nativeEnvironmentCasePreserved= new HashMap<String, String>(); - cacheNativeEnvironment(nativeEnvironmentCasePreserved); - } - return new HashMap<String, String>(nativeEnvironmentCasePreserved); - } - } - - /** - * Query the native environment and store it to the specified cache. - * - * @param cache The environment cache. Must not be <code>null</code>. - */ - private static void cacheNativeEnvironment(Map<String, String> cache) { - Assert.isNotNull(cache); - - try { - String nativeCommand = null; - boolean isWin9xME = false; // see bug 50567 - String fileName = null; - if (Platform.getOS().equals(Constants.OS_WIN32)) { - String osName = System.getProperty("os.name"); //$NON-NLS-1$ - isWin9xME = osName != null && (osName.startsWith("Windows 9") || osName.startsWith("Windows ME")); //$NON-NLS-1$ //$NON-NLS-2$ - if (isWin9xME) { - // Win 95, 98, and ME - // SET might not return therefore we pipe into a file - IPath stateLocation = UIPlugin.getDefault().getStateLocation(); - fileName = stateLocation.toOSString() + File.separator + "env.txt"; //$NON-NLS-1$ - nativeCommand = "command.com /C set > " + fileName; //$NON-NLS-1$ - } else { - // Win NT, 2K, XP - nativeCommand = "cmd.exe /C set"; //$NON-NLS-1$ - } - } else if (!Platform.getOS().equals(Constants.OS_UNKNOWN)) { - nativeCommand = "env"; //$NON-NLS-1$ - } - if (nativeCommand == null) { return; } - Process process = Runtime.getRuntime().exec(nativeCommand); - if (isWin9xME) { - // read piped data on Win 95, 98, and ME - Properties p = new Properties(); - File file = new File(fileName); - InputStream stream = null; - try { - stream = new BufferedInputStream(new FileInputStream(file)); - p.load(stream); - } finally { - if (stream != null) stream.close(); - } - if (!file.delete()) { - file.deleteOnExit(); // if delete() fails try again on VM close - } - for (Enumeration<Object> enumeration = p.keys(); enumeration.hasMoreElements();) { - // Win32's environment variables are case insensitive. Put everything - // to upper case so that (for example) the "PATH" variable will match - // "pAtH" correctly on Windows. - String key = (String)enumeration.nextElement(); - cache.put(key, (String)p.get(key)); - } - } else { - // read process directly on other platforms - // we need to parse out matching '{' and '}' for function declarations in .bash environments - // pattern is [function name]=() { and we must find the '}' on its own line with no trailing ';' - InputStream stream = process.getInputStream(); - InputStreamReader isreader = new InputStreamReader(stream); - BufferedReader reader = new BufferedReader(isreader); - try { - String line = reader.readLine(); - String key = null; - String value = null; - while (line != null) { - int func = line.indexOf("=()"); //$NON-NLS-1$ - if (func > 0) { - key = line.substring(0, func); - // scan until we find the closing '}' with no following chars - value = line.substring(func + 1); - while (line != null && !line.equals("}")) { //$NON-NLS-1$ - line = reader.readLine(); - if (line != null) { - value += line; - } - } - line = reader.readLine(); - } else { - int separator = line.indexOf('='); - if (separator > 0) { - key = line.substring(0, separator); - value = line.substring(separator + 1); - StringBuilder bufValue = new StringBuilder(value); - line = reader.readLine(); - if (line != null) { - // this line has a '=' read ahead to check next line for '=', might be broken on more - // than one line - separator = line.indexOf('='); - while (separator < 0) { - bufValue.append(line.trim()); - line = reader.readLine(); - if (line == null) { - // if next line read is the end of the file quit the loop - break; - } - separator = line.indexOf('='); - } - } - value = bufValue.toString(); - } - } - if (key != null) { - cache.put(key, value); - key = null; - value = null; - } else { - line = reader.readLine(); - } - } - } finally { - reader.close(); - } - } - } catch (IOException e) { - // Native environment-fetching code failed. - // This can easily happen and is not useful to log. - } - } } |