/** Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*********************//* We use APIs that access a so-called Windows "Environment Block",* which looks like an array of jchars like this:** FOO=BAR\u0000 ... GORP=QUUX\u0000\u0000** This data structure has a number of peculiarities we must contend with:* (see: http://windowssdk.msdn.microsoft.com/en-us/library/ms682009.aspx)* - The NUL jchar separators, and a double NUL jchar terminator.* It appears that the Windows implementation requires double NUL* termination even if the environment is empty. We should always* generate environments with double NUL termination, while accepting* empty environments consisting of a single NUL.* - on Windows9x, this is actually an array of 8-bit chars, not jchars,* encoded in the system default encoding.* - The block must be sorted by Unicode value, case-insensitively,* as if folded to upper case.* - There are magic environment variables maintained by Windows* that start with a `=' (!) character. These are used for* Windows drive current directory (e.g. "=C:=C:\WINNT") or the* exit code of the last command (e.g. "=ExitCode=0000001").** Since Java and non-9x Windows speak the same character set, and* even the same encoding, we don't have to deal with unreliable* conversion to byte streams. Just add a few NUL terminators.** System.getenv(String) is case-insensitive, while System.getenv()* returns a map that is case-sensitive, which is consistent with* native Windows APIs.** The non-private methods in this class are not for general use even* within this package. Instead, they are the system-dependent parts* of the system-independent method of the same name. Don't even* think of using this class unless your method's name appears below.** @author Martin Buchholz* @since 1.5*/package java.lang;import java.io.*;import java.util.*;final class ProcessEnvironment extends HashMap<String,String>{private static final long serialVersionUID = -8017839552603542824L;private static String validateName(String name) {// An initial `=' indicates a magic Windows variable name -- OKif (name.indexOf('=', 1) != -1 ||name.indexOf('\u0000') != -1)throw new IllegalArgumentException("Invalid environment variable name: \"" + name + "\"");return name;}private static String validateValue(String value) {if (value.indexOf('\u0000') != -1)throw new IllegalArgumentException("Invalid environment variable value: \"" + value + "\"");return value;}private static String nonNullString(Object o) {if (o == null)throw new NullPointerException();return (String) o;}public String put(String key, String value) {return super.put(validateName(key), validateValue(value));}public String get(Object key) {return super.get(nonNullString(key));}public boolean containsKey(Object key) {return super.containsKey(nonNullString(key));}public boolean containsValue(Object value) {return super.containsValue(nonNullString(value));}public String remove(Object key) {return super.remove(nonNullString(key));}private static class CheckedEntryimplements Map.Entry<String,String>{private final Map.Entry<String,String> e;public CheckedEntry(Map.Entry<String,String> e) {this.e = e;}public String getKey() { return e.getKey();}public String getValue() { return e.getValue();}public String setValue(String value) {return e.setValue(validateValue(value));}public String toString() { return getKey() + "=" + getValue();}public boolean equals(Object o) {return e.equals(o);}public int hashCode() {return e.hashCode();}}private static class CheckedEntrySetextends AbstractSet<Map.Entry<String,String>>{private final Set<Map.Entry<String,String>> s;public CheckedEntrySet(Set<Map.Entry<String,String>> s) {this.s = s;}public int size() {return s.size();}public boolean isEmpty() {return s.isEmpty();}public void clear() { s.clear();}public Iterator<Map.Entry<String,String>> iterator() {return new Iterator<Map.Entry<String,String>>() {Iterator<Map.Entry<String,String>> i = s.iterator();public boolean hasNext() { return i.hasNext();}public Map.Entry<String,String> next() {return new CheckedEntry(i.next());}public void remove() { i.remove();}};}private static Map.Entry<String,String> checkedEntry(Object o) {@SuppressWarnings("unchecked")Map.Entry<String,String> e = (Map.Entry<String,String>) o;nonNullString(e.getKey());nonNullString(e.getValue());return e;}public boolean contains(Object o) {return s.contains(checkedEntry(o));}public boolean remove(Object o) {return s.remove(checkedEntry(o));}}private static class CheckedValues extends AbstractCollection<String> {private final Collection<String> c;public CheckedValues(Collection<String> c) {this.c = c;}public int size() {return c.size();}public boolean isEmpty() {return c.isEmpty();}public void clear() { c.clear();}public Iterator<String> iterator() {return c.iterator();}public boolean contains(Object o) {return c.contains(nonNullString(o));}public boolean remove(Object o) {return c.remove(nonNullString(o));}}private static class CheckedKeySet extends AbstractSet<String> {private final Set<String> s;public CheckedKeySet(Set<String> s) {this.s = s;}public int size() {return s.size();}public boolean isEmpty() {return s.isEmpty();}public void clear() { s.clear();}public Iterator<String> iterator() {return s.iterator();}public boolean contains(Object o) {return s.contains(nonNullString(o));}public boolean remove(Object o) {return s.remove(nonNullString(o));}}public Set<String> keySet() {return new CheckedKeySet(super.keySet());}public Collection<String> values() {return new CheckedValues(super.values());}public Set<Map.Entry<String,String>> entrySet() {return new CheckedEntrySet(super.entrySet());}private static final class NameComparatorimplements Comparator<String> {public int compare(String s1, String s2) {// We can't use String.compareToIgnoreCase since it// canonicalizes to lower case, while Windows// canonicalizes to upper case! For example, "_" should// sort *after* "Z", not before.int n1 = s1.length();int n2 = s2.length();int min = Math.min(n1, n2);for (int i = 0; i < min; i++) {char c1 = s1.charAt(i);char c2 = s2.charAt(i);if (c1 != c2) {c1 = Character.toUpperCase(c1);c2 = Character.toUpperCase(c2);if (c1 != c2)// No overflow because of numeric promotionreturn c1 - c2;}}return n1 - n2;}}private static final class EntryComparatorimplements Comparator<Map.Entry<String,String>> {public int compare(Map.Entry<String,String> e1,Map.Entry<String,String> e2) {return nameComparator.compare(e1.getKey(), e2.getKey());}}// Allow `=' as first char in name, e.g. =C:=C:\DIRstatic final int MIN_NAME_LENGTH = 1;private static final NameComparator nameComparator;private static final EntryComparator entryComparator;private static final ProcessEnvironment theEnvironment;private static final Map<String,String> theUnmodifiableEnvironment;private static final Map<String,String> theCaseInsensitiveEnvironment;static {nameComparator = new NameComparator();entryComparator = new EntryComparator();theEnvironment = new ProcessEnvironment();theUnmodifiableEnvironment= Collections.unmodifiableMap(theEnvironment);String envblock = environmentBlock();int beg, end, eql;for (beg = 0;((end = envblock.indexOf('\u0000', beg )) != -1 &&// An initial `=' indicates a magic Windows variable name -- OK(eql = envblock.indexOf('=' , beg+1)) != -1);beg = end + 1) {// Ignore corrupted environment strings.if (eql < end)theEnvironment.put(envblock.substring(beg, eql),envblock.substring(eql+1,end));}theCaseInsensitiveEnvironment = new TreeMap<>(nameComparator);theCaseInsensitiveEnvironment.putAll(theEnvironment);}private ProcessEnvironment() {super();}private ProcessEnvironment(int capacity) {super(capacity);}// Only for use by System.getenv(String)static String getenv(String name) {// The original implementation used a native call to _wgetenv,// but it turns out that _wgetenv is only consistent with// GetEnvironmentStringsW (for non-ASCII) if `wmain' is used// instead of `main', even in a process created using// CREATE_UNICODE_ENVIRONMENT. Instead we perform the// case-insensitive comparison ourselves. At least this// guarantees that System.getenv().get(String) will be// consistent with System.getenv(String).return theCaseInsensitiveEnvironment.get(name);}// Only for use by System.getenv()static Map<String,String> getenv() {return theUnmodifiableEnvironment;}// Only for use by ProcessBuilder.environment()@SuppressWarnings("unchecked")static Map<String,String> environment() {return (Map<String,String>) theEnvironment.clone();}// Only for use by ProcessBuilder.environment(String[] envp)static Map<String,String> emptyEnvironment(int capacity) {return new ProcessEnvironment(capacity);}private static native String environmentBlock();// Only for use by ProcessImpl.start()String toEnvironmentBlock() {// Sort Unicode-case-insensitively by nameList<Map.Entry<String,String>> list = new ArrayList<>(entrySet());Collections.sort(list, entryComparator);StringBuilder sb = new StringBuilder(size()*30);int cmp = -1;// Some versions of MSVCRT.DLL require SystemRoot to be set.// So, we make sure that it is always set, even if not provided// by the caller.final String SYSTEMROOT = "SystemRoot";for (Map.Entry<String,String> e : list) {String key = e.getKey();String value = e.getValue();if (cmp < 0 && (cmp = nameComparator.compare(key, SYSTEMROOT)) > 0) {// Not set, so add it hereaddToEnvIfSet(sb, SYSTEMROOT);}addToEnv(sb, key, value);}if (cmp < 0) {// Got to end of list and still not foundaddToEnvIfSet(sb, SYSTEMROOT);}if (sb.length() == 0) {// Environment was empty and SystemRoot not set in parentsb.append('\u0000');}// Block is double NUL terminatedsb.append('\u0000');return sb.toString();}// add the environment variable to the child, if it exists in parentprivate static void addToEnvIfSet(StringBuilder sb, String name) {String s = getenv(name);if (s != null)addToEnv(sb, name, s);}private static void addToEnv(StringBuilder sb, String name, String val) {sb.append(name).append('=').append(val).append('\u0000');}static String toEnvironmentBlock(Map<String,String> map) {return map == null ? null :((ProcessEnvironment)map).toEnvironmentBlock();}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。