* Copyright (C) 2010 Robert Futrell
* robert_futrell at users.sourceforge.net
* http://fifesoft.com/rsyntaxtextarea
* This library is distributed under a modified BSD license. See the included
* RSTALanguageSupport.License.txt file for details.
package org.fife.rsta.ac;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
* I/O related utility methods. We should think of a better location for
private static Map DEFAULT_ENV;
* Private constructor to prevent instantiation.
* Gets the environment of the current process. Works with Java 1.4 as
* @return A mapping of environment variable names to values.
private static Map getDefaultEnvMap() {
// If we've already created it...
// In Java 5+, we can just get the environment directly
Method m = System.class.getDeclaredMethod("getenv", null);
DEFAULT_ENV = (Map)m.invoke(null, null);
} catch (Exception e) { // Java 1.4
DEFAULT_ENV = new HashMap();
StringBuffer stdout = new StringBuffer();
if (File.separatorChar=='\\') {
command = "cmd.exe /c set";
command = "/bin/sh -c env";
Process p = Runtime.getRuntime().exec(command);
IOUtil.waitForProcess(p, stdout, null);
} catch (IOException ioe) {
String str = stdout.toString();
BufferedReader r = new BufferedReader(new StringReader(str));
while ((line=r.readLine())!=null) {
int equals = line.indexOf('=');
if (equals>-1) { // Always true
String key = line.substring(0, equals);
String value = line.substring(equals+1);
DEFAULT_ENV.put(key, value);
} catch (IOException ioe) { // Never happens
* Returns the value of an environment variable. This method is here so
* we don't get an exception when calling <tt>System.getenv()</tt> in Java
* 1.4 (which we support).
* @param var The environment variable.
* @return The value of the variable, or <code>null</code> if it is not
public static String getEnvSafely(String var) {
value = System.getenv(var);
} catch (java.lang.Error e) { // Throws exception in 1.4
if (File.separatorChar=='\\') {
String command = "cmd.exe /c set " + var;
StringBuffer stdout = new StringBuffer();
Process p = Runtime.getRuntime().exec(command);
IOUtil.waitForProcess(p, stdout, null);
} catch (IOException ioe) {
// set will return multiple matches if "var" is a prefix of
// other vars, but we'll just check the first line for "var=".
String str = stdout.toString();
int equals = str.indexOf('=');
int newline = str.indexOf('\n');
if (equals==var.length() && newline>equals) {
String test = str.substring(0, var.length());
// Be careful with casing - Windows doesn't always return
// the same casing as what you enter.
if (test.equalsIgnoreCase(var)) {
value = str.substring(var.length()+1, str.length()-1);
String command = "/bin/sh -c env | grep \"var\"=";
StringBuffer stdout = new StringBuffer();
Process p = Runtime.getRuntime().exec(command);
IOUtil.waitForProcess(p, stdout, null);
} catch (IOException ioe) {
// env will return multiple matches if "var" is a prefix of
// other vars, but we'll just check the first line for "var=".
String str = stdout.toString();
int equals = str.indexOf('=');
int newline = str.indexOf('\n');
if (equals==var.length() && newline>equals) {
String test = str.substring(0, var.length());
value = str.substring(var.length()+1, str.length()-1);
* Returns the environment of the current process, with some variables
* possibly added/overwritten. This method works even with Java 1.4.
* @param toAdd The environment variables to add/overwrite in the returned
* array. This array should have an even length, with even indices
* containing variable names and odd indices containing the variable
* @return The environment variables. This array's entries will be of the
* form "<code>name=value</code>", so it can be passed directly
* into <code>Runtime.exec()</code>.
public static String[] getEnvironmentSafely(String[] toAdd) {
Map env = getDefaultEnvMap();
// Put any vars they want to explicitly specify
Map temp = new HashMap(env);
for (int i=0; i<toAdd.length; i+=2) {
temp.put(toAdd[i], toAdd[i+1]);
// Create an array of "name=value" items, like Runtime.exec() wants
String[] vars = new String[count];
for (Iterator j=env.entrySet().iterator(); j.hasNext(); ) {
Map.Entry entry = (Map.Entry)j.next();
vars[i++] = entry.getKey() + "=" + entry.getValue();
* Runs a process, possibly capturing its stdout and/or stderr.
* @param stdout A buffer in which to put stdout, or <code>null</code> if
* you don't want to keep it.
* @param stderr A buffer in which to keep stderr, or <code>null</code>
* if you don't want to keep it.
* @return The return code of the process.
* @throws IOException If an IO error occurs.
// TODO: Allow a timeout to be passed in
public static int waitForProcess(Process p, StringBuffer stdout,
StringBuffer stderr) throws IOException {
InputStream in = p.getInputStream();
InputStream err = p.getErrorStream();
Thread t1 = new Thread(new OutputCollector(in, stdout));
Thread t2 = new Thread(new OutputCollector(err, stderr));
} catch (InterruptedException ie) {
* Utility testing method.
* @param args Command line arguments.
public static void main(String[] args) {
for (int i=0; i<args.length; i++) {
String value = IOUtil.getEnvSafely(args[i]);
System.out.println(args[i] + "=" + value);