001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.exec.environment; 019 020import java.io.BufferedReader; 021import java.io.IOException; 022import java.util.Comparator; 023import java.util.HashMap; 024import java.util.Map; 025import java.util.TreeMap; 026 027import org.apache.commons.exec.CommandLine; 028import org.apache.commons.exec.OS; 029 030/** 031 * Helper class to determine the environment variable 032 * for the OS. Depending on the JDK the environment 033 * variables can be either retrieved directly from the 034 * JVM or requires starting a process to get them running 035 * an OS command line. 036 * 037 * @version $Id: DefaultProcessingEnvironment.java 1636056 2014-11-01 21:12:52Z ggregory $ 038 */ 039public class DefaultProcessingEnvironment { 040 041 /** the line separator of the system */ 042// private static final String LINE_SEPARATOR = System.getProperty("line.separator"); 043 044 /** the environment variables of the process */ 045 protected Map<String, String> procEnvironment; 046 047 /** 048 * Find the list of environment variables for this process. 049 * 050 * @return a map containing the environment variables 051 * @throws IOException obtaining the environment variables failed 052 */ 053 public synchronized Map<String, String> getProcEnvironment() throws IOException { 054 055 if (procEnvironment == null) { 056 procEnvironment = this.createProcEnvironment(); 057 } 058 059 // create a copy of the map just in case that 060 // anyone is going to modifiy it, e.g. removing 061 // or setting an evironment variable 062 final Map<String, String> copy = createEnvironmentMap(); 063 copy.putAll(procEnvironment); 064 return copy; 065 } 066 067 /** 068 * Find the list of environment variables for this process. 069 * 070 * @return a amp containing the environment variables 071 * @throws IOException the operation failed 072 */ 073 protected Map<String, String> createProcEnvironment() throws IOException { 074 if (procEnvironment == null) { 075 final Map<String, String> env = System.getenv(); 076 procEnvironment = createEnvironmentMap(); 077 procEnvironment.putAll(env); 078 } 079 080// No longer needed 081// if (procEnvironment == null) { 082// procEnvironment = createEnvironmentMap(); 083// final BufferedReader in = runProcEnvCommand(); 084// 085// String var = null; 086// String line; 087// while ((line = in.readLine()) != null) { 088// if (line.indexOf('=') == -1) { 089// // Chunk part of previous env var (UNIX env vars can 090// // contain embedded new lines). 091// if (var == null) { 092// var = LINE_SEPARATOR + line; 093// } else { 094// var += LINE_SEPARATOR + line; 095// } 096// } else { 097// // New env var...append the previous one if we have it. 098// if (var != null) { 099// EnvironmentUtils.addVariableToEnvironment(procEnvironment, var); 100// } 101// var = line; 102// } 103// } 104// // Since we "look ahead" before adding, there's one last env var. 105// if (var != null) { 106// EnvironmentUtils.addVariableToEnvironment(procEnvironment, var); 107// } 108// } 109 return procEnvironment; 110 } 111 112 /** 113 * Start a process to list the environment variables. 114 * 115 * @return a reader containing the output of the process 116 * @throws IOException starting the process failed 117 * @deprecated No longer needed 118 */ 119 @Deprecated 120 protected BufferedReader runProcEnvCommand() throws IOException { 121// final ByteArrayOutputStream out = new ByteArrayOutputStream(); 122// final Executor exe = new DefaultExecutor(); 123// exe.setStreamHandler(new PumpStreamHandler(out)); 124// // ignore the exit value - Just try to use what we got 125// exe.execute(getProcEnvCommand()); 126// return new BufferedReader(new StringReader(toString(out))); 127 return null; 128 } 129 130 /** 131 * Determine the OS specific command line to get a list of environment 132 * variables. 133 * 134 * @return the command line 135 * @deprecated No longer needed 136 */ 137 @Deprecated 138 protected CommandLine getProcEnvCommand() { 139// String executable; 140// String[] arguments = null; 141// if (OS.isFamilyOS2()) { 142// // OS/2 - use same mechanism as Windows 2000 143// executable = "cmd"; 144// 145// arguments = new String[] {"/c", "set"}; 146// } else if (OS.isFamilyWindows()) { 147// // Determine if we're running under XP/2000/NT or 98/95 148// if (OS.isFamilyWin9x()) { 149// executable = "command.com"; 150// // Windows 98/95 151// } else { 152// executable = "cmd"; 153// // Windows XP/2000/NT/2003 154// } 155// arguments = new String[] {"/c", "set"}; 156// } else if (OS.isFamilyZOS() || OS.isFamilyUnix()) { 157// // On most systems one could use: /bin/sh -c env 158// 159// // Some systems have /bin/env, others /usr/bin/env, just try 160// if (new File("/bin/env").canRead()) { 161// executable = "/bin/env"; 162// } else if (new File("/usr/bin/env").canRead()) { 163// executable = "/usr/bin/env"; 164// } else { 165// // rely on PATH 166// executable = "env"; 167// } 168// } else if (OS.isFamilyNetware() || OS.isFamilyOS400()) { 169// // rely on PATH 170// executable = "env"; 171// } else { 172// // MAC OS 9 and previous 173// // TODO: I have no idea how to get it, someone must fix it 174// executable = null; 175// } 176 final CommandLine commandLine = null; 177// if (executable != null) { 178// commandLine = new CommandLine(executable); 179// commandLine.addArguments(arguments); 180// } 181 return commandLine; 182 } 183 184// /** 185// * ByteArrayOutputStream#toString doesn't seem to work reliably on OS/390, 186// * at least not the way we use it in the execution context. 187// * 188// * @param bos 189// * the output stream that one wants to read 190// * @return the output stream as a string, read with special encodings in the 191// * case of z/os and os/400 192// */ 193// private String toString(final ByteArrayOutputStream bos) { 194// if (OS.isFamilyZOS()) { 195// try { 196// return bos.toString("Cp1047"); 197// } catch (final java.io.UnsupportedEncodingException e) { 198// // noop default encoding used 199// } 200// } else if (OS.isFamilyOS400()) { 201// try { 202// return bos.toString("Cp500"); 203// } catch (final java.io.UnsupportedEncodingException e) { 204// // noop default encoding used 205// } 206// } 207// return bos.toString(); 208// } 209 210 /** 211 * Creates a map that obeys the casing rules of the current platform for key 212 * lookup. E.g. on a Windows platform, the map keys will be 213 * case-insensitive. 214 * 215 * @return The map for storage of environment variables, never 216 * {@code null}. 217 */ 218 private Map<String, String> createEnvironmentMap() { 219 if (OS.isFamilyWindows()) { 220 return new TreeMap<String, String>(new Comparator<String>() { 221 public int compare(final String key0, final String key1) { 222 return key0.compareToIgnoreCase(key1); 223 } 224 }); 225 } 226 return new HashMap<String, String>(); 227 } 228 229}