jdk/src/windows/classes/java/lang/ProcessEnvironment.java
author ohair
Wed, 06 Apr 2011 22:06:11 -0700
changeset 9035 1255eb81cc2f
parent 7803 56bc97d69d93
child 9500 268f823d9e1c
permissions -rw-r--r--
7033660: Update copyright year to 2011 on any files changed in 2011 Reviewed-by: dholmes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
9035
1255eb81cc2f 7033660: Update copyright year to 2011 on any files changed in 2011
ohair
parents: 7803
diff changeset
     2
 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
/* We use APIs that access a so-called Windows "Environment Block",
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
 * which looks like an array of jchars like this:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
 * FOO=BAR\u0000 ... GORP=QUUX\u0000\u0000
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
 * This data structure has a number of peculiarities we must contend with:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
 * (see: http://windowssdk.msdn.microsoft.com/en-us/library/ms682009.aspx)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
 * - The NUL jchar separators, and a double NUL jchar terminator.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
 *   It appears that the Windows implementation requires double NUL
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
 *   termination even if the environment is empty.  We should always
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
 *   generate environments with double NUL termination, while accepting
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
 *   empty environments consisting of a single NUL.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
 * - on Windows9x, this is actually an array of 8-bit chars, not jchars,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
 *   encoded in the system default encoding.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 * - The block must be sorted by Unicode value, case-insensitively,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
 *   as if folded to upper case.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
 * - There are magic environment variables maintained by Windows
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 *   that start with a `=' (!) character.  These are used for
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
 *   Windows drive current directory (e.g. "=C:=C:\WINNT") or the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 *   exit code of the last command (e.g. "=ExitCode=0000001").
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * Since Java and non-9x Windows speak the same character set, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * even the same encoding, we don't have to deal with unreliable
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * conversion to byte streams.  Just add a few NUL terminators.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * System.getenv(String) is case-insensitive, while System.getenv()
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * returns a map that is case-sensitive, which is consistent with
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * native Windows APIs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * The non-private methods in this class are not for general use even
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * within this package.  Instead, they are the system-dependent parts
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * of the system-independent method of the same name.  Don't even
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * think of using this class unless your method's name appears below.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * @author Martin Buchholz
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * @since 1.5
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
package java.lang;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
import java.io.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
import java.util.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
final class ProcessEnvironment extends HashMap<String,String>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
{
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
    private static String validateName(String name) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
        // An initial `=' indicates a magic Windows variable name -- OK
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
        if (name.indexOf('=', 1)   != -1 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
            name.indexOf('\u0000') != -1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
            throw new IllegalArgumentException
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
                ("Invalid environment variable name: \"" + name + "\"");
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
        return name;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    private static String validateValue(String value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
        if (value.indexOf('\u0000') != -1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
            throw new IllegalArgumentException
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
                ("Invalid environment variable value: \"" + value + "\"");
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
        return value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    private static String nonNullString(Object o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
        if (o == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
            throw new NullPointerException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
        return (String) o;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
    public String put(String key, String value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
        return super.put(validateName(key), validateValue(value));
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    public String get(Object key) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
        return super.get(nonNullString(key));
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    public boolean containsKey(Object key) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
        return super.containsKey(nonNullString(key));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
    public boolean containsValue(Object value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
        return super.containsValue(nonNullString(value));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
    public String remove(Object key) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
        return super.remove(nonNullString(key));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    private static class CheckedEntry
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
        implements Map.Entry<String,String>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
        private final Map.Entry<String,String> e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
        public CheckedEntry(Map.Entry<String,String> e) {this.e = e;}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
        public String getKey()   { return e.getKey();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
        public String getValue() { return e.getValue();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
        public String setValue(String value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
            return e.setValue(validateValue(value));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
        public String toString() { return getKey() + "=" + getValue();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
        public boolean equals(Object o) {return e.equals(o);}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
        public int hashCode()    {return e.hashCode();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    private static class CheckedEntrySet
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
        extends AbstractSet<Map.Entry<String,String>>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
        private final Set<Map.Entry<String,String>> s;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
        public CheckedEntrySet(Set<Map.Entry<String,String>> s) {this.s = s;}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
        public int size()        {return s.size();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
        public boolean isEmpty() {return s.isEmpty();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
        public void clear()      {       s.clear();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
        public Iterator<Map.Entry<String,String>> iterator() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
            return new Iterator<Map.Entry<String,String>>() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
                Iterator<Map.Entry<String,String>> i = s.iterator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
                public boolean hasNext() { return i.hasNext();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
                public Map.Entry<String,String> next() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
                    return new CheckedEntry(i.next());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
                public void remove() { i.remove();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
            };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
        private static Map.Entry<String,String> checkedEntry (Object o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
            Map.Entry<String,String> e = (Map.Entry<String,String>) o;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
            nonNullString(e.getKey());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
            nonNullString(e.getValue());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
            return e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
        public boolean contains(Object o) {return s.contains(checkedEntry(o));}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
        public boolean remove(Object o)   {return s.remove(checkedEntry(o));}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
    private static class CheckedValues extends AbstractCollection<String> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
        private final Collection<String> c;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
        public CheckedValues(Collection<String> c) {this.c = c;}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
        public int size()                  {return c.size();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
        public boolean isEmpty()           {return c.isEmpty();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
        public void clear()                {       c.clear();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
        public Iterator<String> iterator() {return c.iterator();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
        public boolean contains(Object o)  {return c.contains(nonNullString(o));}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
        public boolean remove(Object o)    {return c.remove(nonNullString(o));}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
    private static class CheckedKeySet extends AbstractSet<String> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
        private final Set<String> s;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
        public CheckedKeySet(Set<String> s) {this.s = s;}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        public int size()                  {return s.size();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
        public boolean isEmpty()           {return s.isEmpty();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        public void clear()                {       s.clear();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
        public Iterator<String> iterator() {return s.iterator();}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
        public boolean contains(Object o)  {return s.contains(nonNullString(o));}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
        public boolean remove(Object o)    {return s.remove(nonNullString(o));}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
    public Set<String> keySet() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
        return new CheckedKeySet(super.keySet());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
    public Collection<String> values() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
        return new CheckedValues(super.values());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
    public Set<Map.Entry<String,String>> entrySet() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
        return new CheckedEntrySet(super.entrySet());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
    private static final class NameComparator
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        implements Comparator<String> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
        public int compare(String s1, String s2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
            // We can't use String.compareToIgnoreCase since it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
            // canonicalizes to lower case, while Windows
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
            // canonicalizes to upper case!  For example, "_" should
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
            // sort *after* "Z", not before.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
            int n1 = s1.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
            int n2 = s2.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
            int min = Math.min(n1, n2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
            for (int i = 0; i < min; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
                char c1 = s1.charAt(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
                char c2 = s2.charAt(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
                if (c1 != c2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
                    c1 = Character.toUpperCase(c1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
                    c2 = Character.toUpperCase(c2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
                    if (c1 != c2)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
                        // No overflow because of numeric promotion
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
                        return c1 - c2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
            return n1 - n2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
    private static final class EntryComparator
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
        implements Comparator<Map.Entry<String,String>> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
        public int compare(Map.Entry<String,String> e1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
                           Map.Entry<String,String> e2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
            return nameComparator.compare(e1.getKey(), e2.getKey());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
    // Allow `=' as first char in name, e.g. =C:=C:\DIR
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
    static final int MIN_NAME_LENGTH = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
    private static final NameComparator nameComparator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
    private static final EntryComparator entryComparator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
    private static final ProcessEnvironment theEnvironment;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
    private static final Map<String,String> theUnmodifiableEnvironment;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
    private static final Map<String,String> theCaseInsensitiveEnvironment;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
    static {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
        nameComparator  = new NameComparator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
        entryComparator = new EntryComparator();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
        theEnvironment  = new ProcessEnvironment();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        theUnmodifiableEnvironment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            = Collections.unmodifiableMap(theEnvironment);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
        String envblock = environmentBlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
        int beg, end, eql;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        for (beg = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
             ((end = envblock.indexOf('\u0000', beg  )) != -1 &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
              // An initial `=' indicates a magic Windows variable name -- OK
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
              (eql = envblock.indexOf('='     , beg+1)) != -1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
             beg = end + 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
            // Ignore corrupted environment strings.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
            if (eql < end)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
                theEnvironment.put(envblock.substring(beg, eql),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
                                   envblock.substring(eql+1,end));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
7803
56bc97d69d93 6880112: Project Coin: Port JDK core library code to use diamond operator
smarks
parents: 5506
diff changeset
   253
        theCaseInsensitiveEnvironment = new TreeMap<>(nameComparator);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
        theCaseInsensitiveEnvironment.putAll(theEnvironment);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
    private ProcessEnvironment() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        super();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
    private ProcessEnvironment(int capacity) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
        super(capacity);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
    // Only for use by System.getenv(String)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
    static String getenv(String name) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
        // The original implementation used a native call to _wgetenv,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
        // but it turns out that _wgetenv is only consistent with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
        // GetEnvironmentStringsW (for non-ASCII) if `wmain' is used
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
        // instead of `main', even in a process created using
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
        // CREATE_UNICODE_ENVIRONMENT.  Instead we perform the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
        // case-insensitive comparison ourselves.  At least this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
        // guarantees that System.getenv().get(String) will be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
        // consistent with System.getenv(String).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
        return theCaseInsensitiveEnvironment.get(name);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
    // Only for use by System.getenv()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
    static Map<String,String> getenv() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        return theUnmodifiableEnvironment;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
    // Only for use by ProcessBuilder.environment()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
    static Map<String,String> environment() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
        return (Map<String,String>) theEnvironment.clone();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
    // Only for use by Runtime.exec(...String[]envp...)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
    static Map<String,String> emptyEnvironment(int capacity) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
        return new ProcessEnvironment(capacity);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
    private static native String environmentBlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
    // Only for use by ProcessImpl.start()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
    String toEnvironmentBlock() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
        // Sort Unicode-case-insensitively by name
7803
56bc97d69d93 6880112: Project Coin: Port JDK core library code to use diamond operator
smarks
parents: 5506
diff changeset
   298
        List<Map.Entry<String,String>> list = new ArrayList<>(entrySet());
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        Collections.sort(list, entryComparator);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        StringBuilder sb = new StringBuilder(size()*30);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
        for (Map.Entry<String,String> e : list)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
            sb.append(e.getKey())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
              .append('=')
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
              .append(e.getValue())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
              .append('\u0000');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
        // Ensure double NUL termination,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
        // even if environment is empty.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
        if (sb.length() == 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
            sb.append('\u0000');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
        sb.append('\u0000');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
        return sb.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
    static String toEnvironmentBlock(Map<String,String> map) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
        return map == null ? null :
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
            ((ProcessEnvironment)map).toEnvironmentBlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
}