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 *      https://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.HashMap;
023import java.util.Map;
024import java.util.TreeMap;
025
026import org.apache.commons.exec.CommandLine;
027import org.apache.commons.exec.OS;
028
029/**
030 * Helper class to determine the environment variable for the OS. Depending on the JDK the environment variables can be either retrieved directly from the JVM
031 * or requires starting a process to get them running an OS command line.
032 */
033public class DefaultProcessingEnvironment {
034
035    /** The environment variables of the process */
036    protected Map<String, String> procEnvironment;
037
038    /**
039     * Constructs a new instance.
040     */
041    public DefaultProcessingEnvironment() {
042        // empty
043    }
044
045    /**
046     * Creates a map that obeys the casing rules of the current platform for key lookup. E.g. on a Windows platform, the map keys will be case-insensitive.
047     *
048     * @return The map for storage of environment variables, never {@code null}.
049     */
050    private Map<String, String> createEnvironmentMap() {
051        if (OS.isFamilyWindows()) {
052            return new TreeMap<>(String::compareToIgnoreCase);
053        }
054        return new HashMap<>();
055    }
056
057    /**
058     * Creates the list of environment variables for this process.
059     *
060     * @return a amp containing the environment variables.
061     * @throws IOException the operation failed.
062     */
063    protected Map<String, String> createProcEnvironment() throws IOException {
064        if (procEnvironment == null) {
065            procEnvironment = createEnvironmentMap();
066            procEnvironment.putAll(System.getenv());
067        }
068        return procEnvironment;
069    }
070
071    /**
072     * Determine the OS specific command line to get a list of environment variables.
073     *
074     * @return the command line.
075     * @deprecated No longer needed.
076     */
077    @Deprecated
078    protected CommandLine getProcEnvCommand() {
079//        String executable;
080//        String[] arguments = null;
081//        if (OS.isFamilyOS2()) {
082//            // OS/2 - use same mechanism as Windows 2000
083//            executable = "cmd";
084//
085//            arguments = new String[] {"/c", "set"};
086//        } else if (OS.isFamilyWindows()) {
087//            // Determine if we're running under XP/2000/NT or 98/95
088//            if (OS.isFamilyWin9x()) {
089//                executable = "command.com";
090//                // Windows 98/95
091//            } else {
092//                executable = "cmd";
093//                // Windows XP/2000/NT/2003
094//            }
095//            arguments = new String[] {"/c", "set"};
096//        } else if (OS.isFamilyZOS() || OS.isFamilyUnix()) {
097//            // On most systems one could use: /bin/sh -c env
098//
099//            // Some systems have /bin/env, others /usr/bin/env, just try
100//            if (new File("/bin/env").canRead()) {
101//                executable = "/bin/env";
102//            } else if (new File("/usr/bin/env").canRead()) {
103//                executable = "/usr/bin/env";
104//            } else {
105//                // rely on PATH
106//                executable = "env";
107//            }
108//        } else if (OS.isFamilyNetware() || OS.isFamilyOS400()) {
109//            // rely on PATH
110//            executable = "env";
111//        } else {
112//            // macOS 9 and previous
113//            // TODO: I have no idea how to get it, someone must fix it
114//            executable = null;
115//        }
116        final CommandLine commandLine = null;
117//        if (executable != null) {
118//            commandLine = new CommandLine(executable);
119//            commandLine.addArguments(arguments);
120//        }
121        return commandLine;
122    }
123
124    /**
125     * Gets the list of environment variables for this process.
126     *
127     * @return a map containing the environment variables.
128     * @throws IOException obtaining the environment variables failed.
129     */
130    public synchronized Map<String, String> getProcEnvironment() throws IOException {
131        if (procEnvironment == null) {
132            procEnvironment = createProcEnvironment();
133        }
134        // create a copy of the map just in case that
135        // anyone is going to modifiy it, e.g. removing
136        // or setting an evironment variable
137        final Map<String, String> copy = createEnvironmentMap();
138        copy.putAll(procEnvironment);
139        return copy;
140    }
141
142    /**
143     * Runs a process to list the environment variables.
144     *
145     * @return a reader containing the output of the process.
146     * @throws IOException starting the process failed.
147     * @deprecated No longer needed.
148     */
149    @Deprecated
150    protected BufferedReader runProcEnvCommand() throws IOException {
151//        final ByteArrayOutputStream out = new ByteArrayOutputStream();
152//        final Executor exe = DefaultExecutor.builder().get();
153//        exe.setStreamHandler(new PumpStreamHandler(out));
154//        // ignore the exit value - Just try to use what we got
155//        exe.execute(getProcEnvCommand());
156//        return new BufferedReader(new StringReader(toString(out)));
157        return null;
158    }
159
160}