001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019
020package org.apache.commons.exec.environment;
021
022import java.io.BufferedReader;
023import java.io.IOException;
024import java.util.HashMap;
025import java.util.Map;
026import java.util.TreeMap;
027
028import org.apache.commons.exec.CommandLine;
029import org.apache.commons.exec.OS;
030
031/**
032 * 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
033 * or requires starting a process to get them running an OS command line.
034 */
035public class DefaultProcessingEnvironment {
036
037    /** The environment variables of the process */
038    protected Map<String, String> procEnvironment;
039
040    /**
041     * Constructs a new instance.
042     */
043    public DefaultProcessingEnvironment() {
044        // empty
045    }
046
047    /**
048     * 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.
049     *
050     * @return The map for storage of environment variables, never {@code null}.
051     */
052    private Map<String, String> createEnvironmentMap() {
053        if (OS.isFamilyWindows()) {
054            return new TreeMap<>(String::compareToIgnoreCase);
055        }
056        return new HashMap<>();
057    }
058
059    /**
060     * Creates the list of environment variables for this process.
061     *
062     * @return a map containing the environment variables.
063     * @throws IOException the operation failed.
064     */
065    protected Map<String, String> createProcEnvironment() throws IOException {
066        if (procEnvironment == null) {
067            procEnvironment = createEnvironmentMap();
068            procEnvironment.putAll(System.getenv());
069        }
070        return procEnvironment;
071    }
072
073    /**
074     * Determine the OS specific command line to get a list of environment variables.
075     *
076     * @return the command line.
077     * @deprecated No longer needed.
078     */
079    @Deprecated
080    protected CommandLine getProcEnvCommand() {
081//        String executable;
082//        String[] arguments = null;
083//        if (OS.isFamilyOS2()) {
084//            // OS/2 - use same mechanism as Windows 2000
085//            executable = "cmd";
086//
087//            arguments = new String[] {"/c", "set"};
088//        } else if (OS.isFamilyWindows()) {
089//            // Determine if we're running under XP/2000/NT or 98/95
090//            if (OS.isFamilyWin9x()) {
091//                executable = "command.com";
092//                // Windows 98/95
093//            } else {
094//                executable = "cmd";
095//                // Windows XP/2000/NT/2003
096//            }
097//            arguments = new String[] {"/c", "set"};
098//        } else if (OS.isFamilyZOS() || OS.isFamilyUnix()) {
099//            // On most systems one could use: /bin/sh -c env
100//
101//            // Some systems have /bin/env, others /usr/bin/env, just try
102//            if (new File("/bin/env").canRead()) {
103//                executable = "/bin/env";
104//            } else if (new File("/usr/bin/env").canRead()) {
105//                executable = "/usr/bin/env";
106//            } else {
107//                // rely on PATH
108//                executable = "env";
109//            }
110//        } else if (OS.isFamilyNetware() || OS.isFamilyOS400()) {
111//            // rely on PATH
112//            executable = "env";
113//        } else {
114//            // macOS 9 and previous
115//            // TODO: I have no idea how to get it, someone must fix it
116//            executable = null;
117//        }
118        final CommandLine commandLine = null;
119//        if (executable != null) {
120//            commandLine = new CommandLine(executable);
121//            commandLine.addArguments(arguments);
122//        }
123        return commandLine;
124    }
125
126    /**
127     * Gets the list of environment variables for this process.
128     *
129     * @return a map containing the environment variables.
130     * @throws IOException obtaining the environment variables failed.
131     */
132    public synchronized Map<String, String> getProcEnvironment() throws IOException {
133        if (procEnvironment == null) {
134            procEnvironment = createProcEnvironment();
135        }
136        // create a copy of the map just in case that
137        // anyone is going to modify it, e.g. removing
138        // or setting an environment variable
139        final Map<String, String> copy = createEnvironmentMap();
140        copy.putAll(procEnvironment);
141        return copy;
142    }
143
144    /**
145     * Runs a process to list the environment variables.
146     *
147     * @return a reader containing the output of the process.
148     * @throws IOException starting the process failed.
149     * @deprecated No longer needed.
150     */
151    @Deprecated
152    protected BufferedReader runProcEnvCommand() throws IOException {
153//        final ByteArrayOutputStream out = new ByteArrayOutputStream();
154//        final Executor exe = DefaultExecutor.builder().get();
155//        exe.setStreamHandler(new PumpStreamHandler(out));
156//        // ignore the exit value - Just try to use what we got
157//        exe.execute(getProcEnvCommand());
158//        return new BufferedReader(new StringReader(toString(out)));
159        return null;
160    }
161
162}