/*
* ProActive Parallel Suite(TM):
* The Open Source library for parallel and distributed
* Workflows & Scheduling, Orchestration, Cloud Automation
* and Big Data Analysis on Enterprise Grids & Clouds.
*
* Copyright (c) 2007 - 2017 ActiveEon
* Contact: contact@activeeon.com
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation: version 3 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* If needed, contact us to obtain a release under GPL Version 2 or 3
* or a different license than the AGPL.
*/
package org.ow2.proactive.utils;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import com.sun.jna.Library;
import com.sun.jna.Native;
/**
* Environment this class uses JNA to change the System Environment variables from the current JVM
* <p>
* It changes both the shallow HashMap copy of the environment held by Java and the real libC environment
*
* @author The ProActive Team
*/
public class Environment {
public static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(Environment.class);
/*
* // for JNI:
* public static class LibC {
* public native int setenv(String name, String value, int overwrite);
* public native int unsetenv(String name);
*
* LibC() {
* System.loadLibrary("Environment_LibC");
* }
* }
* static LibC libc = new LibC();
*/
public interface WinLibC extends Library {
int _putenv(String name);
}
public interface LinuxLibC extends Library {
int setenv(String name, String value, int overwrite);
int unsetenv(String name);
}
public static class POSIX {
Object libc = null;
public POSIX() {
String osName = System.getProperty("os.name");
OperatingSystem operatingSystem = OperatingSystem.resolveOrError(osName);
OperatingSystemFamily family = operatingSystem.getFamily();
String[] linuxLibcNames = new String[] { "c", "libc.so.6", "libc.so.5", "libc.so.7" };
libc = null;
switch (family) {
case LINUX:
case UNIX:
case MAC:
for (String libName : linuxLibcNames) {
try {
libc = Native.loadLibrary(libName, LinuxLibC.class);
break;
} catch (Throwable e) {
logger.debug("[Warning] could not load library '" + libName + "', skipping...", e);
}
}
break;
case WINDOWS:
try {
libc = Native.loadLibrary("msvcrt", WinLibC.class);
} catch (Throwable e) {
logger.debug("[Warning] could not load library 'msvcrt', skipping...", e);
}
break;
default:
// we don't initialize libc
}
if (libc == null) {
logger.warn("Couldn't load the C library native env modification will be disabled.");
}
}
public int setenv(String name, String value, int overwrite) {
if (libc != null) {
if (libc instanceof LinuxLibC) {
return ((LinuxLibC) libc).setenv(name, value, overwrite);
} else {
return ((WinLibC) libc)._putenv(name + "=" + value);
}
}
return 0;
}
public int unsetenv(String name) {
if (libc != null) {
if (libc instanceof LinuxLibC) {
return ((LinuxLibC) libc).unsetenv(name);
} else {
return ((WinLibC) libc)._putenv(name + "=");
}
}
return 0;
}
}
private static POSIX posix;
static POSIX getPOSIXinstance() {
if (posix == null) {
posix = new POSIX();
}
return posix;
}
public static int unsetenv(String name) {
Map<String, String> map = getenv();
map.remove(name);
Map<String, String> env2 = getwinenv();
env2.remove(name);
return getPOSIXinstance().unsetenv(name);
}
public static int setenv(String name, String value, boolean overwrite) {
if (name.lastIndexOf("=") != -1) {
throw new IllegalArgumentException("Environment variable cannot contain '='");
}
Map<String, String> map = getenv();
boolean contains = map.containsKey(name);
if (!contains || overwrite) {
map.put(name, value);
Map<String, String> env2 = getwinenv();
env2.put(name, value);
}
return getPOSIXinstance().setenv(name, value, overwrite ? 1 : 0);
}
@SuppressWarnings("unchecked")
public static Map<String, String> getwinenv() {
try {
Class<?> sc = Class.forName("java.lang.ProcessEnvironment");
Field caseinsensitive = sc.getDeclaredField("theCaseInsensitiveEnvironment");
caseinsensitive.setAccessible(true);
return (Map<String, String>) caseinsensitive.get(null);
} catch (Exception e) {
logger.debug("Error when reading the JVM System Environment Cache : " + e.getMessage());
}
return new HashMap<>();
}
@SuppressWarnings("unchecked")
public static Map<String, String> getenv() {
try {
Map<String, String> theUnmodifiableEnvironment = System.getenv();
Class<?> cu = theUnmodifiableEnvironment.getClass();
Field m = cu.getDeclaredField("m");
m.setAccessible(true);
return (Map<String, String>) m.get(theUnmodifiableEnvironment);
} catch (Exception ex2) {
logger.debug("Error when reading the JVM System Environment Cache : " + ex2.getMessage());
}
return new HashMap<>();
}
public static void main(String[] args) throws InterruptedException {
setenv("TEST", "foo", true);
String val = getenv().get("TEST");
System.out.println(val);
Thread.sleep(10000);
}
}