Changeset 19100 in josm


Ignore:
Timestamp:
2024-06-11T21:21:51+02:00 (3 weeks ago)
Author:
taylor.smock
Message:

Fix #23725: Drop Java 8 code in WinRegistry

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/tools/WinRegistry.java

    r16628 r19100  
    2929     * See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms724836(v=vs.85).aspx">Predefined Keys</a>
    3030     */
    31     public static final int HKEY_CURRENT_USER = 0x80000001;
     31    public static final long HKEY_CURRENT_USER = 0x80000001L;
    3232
    3333    /**
     
    3939     * See <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms724836(v=vs.85).aspx">Predefined Keys</a>
    4040     */
    41     public static final int HKEY_LOCAL_MACHINE = 0x80000002;
     41    public static final long HKEY_LOCAL_MACHINE = 0x80000002L;
    4242
    4343    private static final long REG_SUCCESS = 0L;
    4444
    4545    private static final int KEY_READ = 0x20019;
    46     private static final Preferences userRoot = Preferences.userRoot();
    47     private static final Preferences systemRoot = Preferences.systemRoot();
    48     private static final Class<? extends Preferences> userClass = userRoot.getClass();
    49     private static final Method regOpenKey;
    50     private static final Method regCloseKey;
    51     private static final Method regQueryValueEx;
    52     private static final Method regEnumValue;
    53     private static final Method regQueryInfoKey;
    54     private static final Method regEnumKeyEx;
    55 
    56     private static boolean java11;
     46    private static final Preferences USER_ROOT = Preferences.userRoot();
     47    private static final Preferences SYSTEM_ROOT = Preferences.systemRoot();
     48    private static final Class<? extends Preferences> USER_CLASS = USER_ROOT.getClass();
     49    private static final String HKEY_EQ = "hkey=";
     50
     51    /**
     52     * Wrapper for Windows registry API RegOpenKey(long, byte[], int)
     53     * Returns {@code long[]}
     54     */
     55    private static final Method REG_OPEN_KEY;
     56    /**
     57     * Wrapper for Windows registry API RegCloseKey(long)
     58     * Returns {@code int}
     59     */
     60    private static final Method REG_CLOSE_KEY;
     61    /**
     62     * Wrapper for Windows registry API RegQueryValueEx(long, byte[])
     63     * Returns {@code byte[]}
     64     */
     65    private static final Method REG_QUERY_VALUE_EX;
     66    /**
     67     * Wrapper for Windows registry API RegEnumValue(long, int, int)
     68     * Returns {@code byte[]}
     69     */
     70    private static final Method REG_ENUM_VALUE;
     71    /**
     72     * Wrapper for RegQueryInfoKey(long)
     73     * Returns {@code long[]}
     74     */
     75    private static final Method REG_QUERY_INFO_KEY;
     76    /**
     77     * Wrapper for RegEnumKeyEx(long, int, int)
     78     * Returns {@code byte[]}
     79     */
     80    private static final Method REG_ENUM_KEY_EX;
    5781
    5882    static {
    59         regOpenKey = getDeclaredMethod("WindowsRegOpenKey", int.class, byte[].class, int.class);
    60         regCloseKey = getDeclaredMethod("WindowsRegCloseKey", int.class);
    61         regQueryValueEx = getDeclaredMethod("WindowsRegQueryValueEx", int.class, byte[].class);
    62         regEnumValue = getDeclaredMethod("WindowsRegEnumValue", int.class, int.class, int.class);
    63         regQueryInfoKey = getDeclaredMethod("WindowsRegQueryInfoKey1", int.class);
    64         regEnumKeyEx = getDeclaredMethod("WindowsRegEnumKeyEx", int.class, int.class, int.class);
    65         ReflectionUtils.setObjectsAccessible(regOpenKey, regCloseKey, regQueryValueEx, regEnumValue, regQueryInfoKey, regEnumKeyEx);
     83        REG_OPEN_KEY = getDeclaredMethod("WindowsRegOpenKey", long.class, byte[].class, int.class);
     84        REG_CLOSE_KEY = getDeclaredMethod("WindowsRegCloseKey", long.class);
     85        REG_QUERY_VALUE_EX = getDeclaredMethod("WindowsRegQueryValueEx", long.class, byte[].class);
     86        REG_ENUM_VALUE = getDeclaredMethod("WindowsRegEnumValue", long.class, int.class, int.class);
     87        REG_QUERY_INFO_KEY = getDeclaredMethod("WindowsRegQueryInfoKey1", long.class);
     88        REG_ENUM_KEY_EX = getDeclaredMethod("WindowsRegEnumKeyEx", long.class, int.class, int.class);
     89        ReflectionUtils.setObjectsAccessible(REG_OPEN_KEY, REG_CLOSE_KEY, REG_QUERY_VALUE_EX, REG_ENUM_VALUE,
     90                REG_QUERY_INFO_KEY, REG_ENUM_KEY_EX);
    6691    }
    6792
    6893    private static Method getDeclaredMethod(String name, Class<?>... parameterTypes) {
    6994        try {
    70             return userClass.getDeclaredMethod(name, parameterTypes);
     95            return USER_CLASS.getDeclaredMethod(name, parameterTypes);
    7196        } catch (NoSuchMethodException e) {
    72             if (parameterTypes.length > 0 && parameterTypes[0] == int.class) {
    73                 // JDK-8198899: change of signature in Java 11. Old signature to drop when we switch to Java 11
    74                 Class<?>[] parameterTypesCopy = Utils.copyArray(parameterTypes);
    75                 parameterTypesCopy[0] = long.class;
    76                 java11 = true;
    77                 return getDeclaredMethod(name, parameterTypesCopy);
    78             }
    7997            Logging.log(Logging.LEVEL_ERROR, "Unable to find WindowsReg method", e);
    8098            return null;
     
    83101            return null;
    84102        }
    85     }
    86 
    87     private static Number hkey(int key) {
    88         return java11 ? ((Number) Long.valueOf(key)) : ((Number) Integer.valueOf(key));
    89103    }
    90104
     
    102116     * @throws IllegalAccessException if Java language access control is enforced and the underlying method is inaccessible
    103117     * @throws InvocationTargetException if the underlying method throws an exception
    104      */
    105     public static String readString(int hkey, String key, String valueName)
     118     * @since 19100 (method definition)
     119     */
     120    public static String readString(long hkey, String key, String valueName)
    106121            throws IllegalAccessException, InvocationTargetException {
    107122        if (hkey == HKEY_LOCAL_MACHINE) {
    108             return readString(systemRoot, hkey, key, valueName);
     123            return readString(SYSTEM_ROOT, hkey, key, valueName);
    109124        } else if (hkey == HKEY_CURRENT_USER) {
    110             return readString(userRoot, hkey, key, valueName);
     125            return readString(USER_ROOT, hkey, key, valueName);
    111126        } else {
    112             throw new IllegalArgumentException("hkey=" + hkey);
     127            throw new IllegalArgumentException(HKEY_EQ + hkey);
    113128        }
    114129    }
     
    123138     * @throws InvocationTargetException if the underlying method throws an exception
    124139     */
    125     public static Map<String, String> readStringValues(int hkey, String key)
     140    public static Map<String, String> readStringValues(long hkey, String key)
    126141            throws IllegalAccessException, InvocationTargetException {
    127142        if (hkey == HKEY_LOCAL_MACHINE) {
    128             return readStringValues(systemRoot, hkey, key);
     143            return readStringValues(SYSTEM_ROOT, hkey, key);
    129144        } else if (hkey == HKEY_CURRENT_USER) {
    130             return readStringValues(userRoot, hkey, key);
     145            return readStringValues(USER_ROOT, hkey, key);
    131146        } else {
    132             throw new IllegalArgumentException("hkey=" + hkey);
     147            throw new IllegalArgumentException(HKEY_EQ + hkey);
    133148        }
    134149    }
     
    143158     * @throws InvocationTargetException if the underlying method throws an exception
    144159     */
    145     public static List<String> readStringSubKeys(int hkey, String key)
     160    public static List<String> readStringSubKeys(long hkey, String key)
    146161            throws IllegalAccessException, InvocationTargetException {
    147162        if (hkey == HKEY_LOCAL_MACHINE) {
    148             return readStringSubKeys(systemRoot, hkey, key);
     163            return readStringSubKeys(SYSTEM_ROOT, hkey, key);
    149164        } else if (hkey == HKEY_CURRENT_USER) {
    150             return readStringSubKeys(userRoot, hkey, key);
     165            return readStringSubKeys(USER_ROOT, hkey, key);
    151166        } else {
    152             throw new IllegalArgumentException("hkey=" + hkey);
     167            throw new IllegalArgumentException(HKEY_EQ + hkey);
    153168        }
    154169    }
     
    156171    // =====================
    157172
    158     private static Number getNumber(Object array, int index) {
    159         if (array instanceof int[]) {
    160             return ((int[]) array)[index];
    161         } else if (array instanceof long[]) {
     173    private static long getNumber(Object array, int index) {
     174        if (array instanceof long[]) {
    162175            return ((long[]) array)[index];
    163176        }
     
    165178    }
    166179
    167     private static String readString(Preferences root, int hkey, String key, String value)
    168             throws IllegalAccessException, InvocationTargetException {
    169         if (regOpenKey == null || regQueryValueEx == null || regCloseKey == null) {
    170             return null;
    171         }
    172         // Need to capture both int[] (Java 8-10) and long[] (Java 11+)
    173         Object handles = regOpenKey.invoke(root, hkey(hkey), toCstr(key), Integer.valueOf(KEY_READ));
    174         if (getNumber(handles, 1).longValue() != REG_SUCCESS) {
    175             return null;
    176         }
    177         byte[] valb = (byte[]) regQueryValueEx.invoke(root, getNumber(handles, 0), toCstr(value));
    178         regCloseKey.invoke(root, getNumber(handles, 0));
     180    private static String readString(Preferences root, long hkey, String key, String value)
     181            throws IllegalAccessException, InvocationTargetException {
     182        if (REG_OPEN_KEY == null || REG_QUERY_VALUE_EX == null || REG_CLOSE_KEY == null) {
     183            return null;
     184        }
     185        Object handles = REG_OPEN_KEY.invoke(root, hkey, toCstr(key), KEY_READ);
     186        if (getNumber(handles, 1) != REG_SUCCESS) {
     187            return null;
     188        }
     189        byte[] valb = (byte[]) REG_QUERY_VALUE_EX.invoke(root, getNumber(handles, 0), toCstr(value));
     190        REG_CLOSE_KEY.invoke(root, getNumber(handles, 0));
    179191        return (valb != null ? new String(valb, StandardCharsets.UTF_8).trim() : null);
    180192    }
    181193
    182     private static Map<String, String> readStringValues(Preferences root, int hkey, String key)
    183             throws IllegalAccessException, InvocationTargetException {
    184         if (regOpenKey == null || regQueryInfoKey == null || regEnumValue == null || regCloseKey == null) {
     194    private static Map<String, String> readStringValues(Preferences root, long hkey, String key)
     195            throws IllegalAccessException, InvocationTargetException {
     196        if (REG_OPEN_KEY == null || REG_QUERY_INFO_KEY == null || REG_ENUM_VALUE == null || REG_CLOSE_KEY == null) {
    185197            return Collections.emptyMap();
    186198        }
    187199        HashMap<String, String> results = new HashMap<>();
    188         // Need to capture both int[] (Java 8-10) and long[] (Java 11+)
    189         Object handles = regOpenKey.invoke(root, hkey(hkey), toCstr(key), Integer.valueOf(KEY_READ));
    190         if (getNumber(handles, 1).longValue() != REG_SUCCESS) {
     200        Object handles = REG_OPEN_KEY.invoke(root, hkey, toCstr(key), KEY_READ);
     201        if (getNumber(handles, 1) != REG_SUCCESS) {
    191202            return Collections.emptyMap();
    192203        }
    193         // Need to capture both int[] (Java 8-10) and long[] (Java 11+)
    194         Object info = regQueryInfoKey.invoke(root, getNumber(handles, 0));
    195 
    196         int count = getNumber(info, 0).intValue();
    197         int maxlen = getNumber(info, 3).intValue();
     204        Object info = REG_QUERY_INFO_KEY.invoke(root, getNumber(handles, 0));
     205
     206        int count = Math.toIntExact(getNumber(info, 0));
     207        int maxlen = Math.toIntExact(getNumber(info, 3));
    198208        for (int index = 0; index < count; index++) {
    199             byte[] name = (byte[]) regEnumValue.invoke(root, getNumber(handles, 0), Integer.valueOf(index), Integer.valueOf(maxlen + 1));
     209            byte[] name = (byte[]) REG_ENUM_VALUE.invoke(root, getNumber(handles, 0), index, maxlen + 1);
    200210            String value = readString(hkey, key, new String(name, StandardCharsets.UTF_8));
    201211            results.put(new String(name, StandardCharsets.UTF_8).trim(), value);
    202212        }
    203         regCloseKey.invoke(root, getNumber(handles, 0));
     213        REG_CLOSE_KEY.invoke(root, getNumber(handles, 0));
    204214        return Collections.unmodifiableMap(results);
    205215    }
    206216
    207     private static List<String> readStringSubKeys(Preferences root, int hkey, String key)
    208             throws IllegalAccessException, InvocationTargetException {
    209         if (regOpenKey == null || regQueryInfoKey == null || regEnumKeyEx == null || regCloseKey == null) {
     217    private static List<String> readStringSubKeys(Preferences root, long hkey, String key)
     218            throws IllegalAccessException, InvocationTargetException {
     219        if (REG_OPEN_KEY == null || REG_QUERY_INFO_KEY == null || REG_ENUM_KEY_EX == null || REG_CLOSE_KEY == null) {
    210220            return Collections.emptyList();
    211221        }
    212222        List<String> results = new ArrayList<>();
    213         // Need to capture both int[] (Java 8-10) and long[] (Java 11+)
    214         Object handles = regOpenKey.invoke(root, hkey(hkey), toCstr(key), Integer.valueOf(KEY_READ));
    215         if (getNumber(handles, 1).longValue() != REG_SUCCESS) {
     223        Object handles = REG_OPEN_KEY.invoke(root, hkey, toCstr(key), KEY_READ);
     224        if (getNumber(handles, 1) != REG_SUCCESS) {
    216225            return Collections.emptyList();
    217226        }
    218         // Need to capture both int[] (Java 8-10) and long[] (Java 11+)
    219         Object info = regQueryInfoKey.invoke(root, getNumber(handles, 0));
    220 
    221         int count = getNumber(info, 0).intValue();
    222         int maxlen = getNumber(info, 3).intValue();
     227        Object info = REG_QUERY_INFO_KEY.invoke(root, getNumber(handles, 0));
     228
     229        int count = Math.toIntExact(getNumber(info, 0));
     230        int maxlen = Math.toIntExact(getNumber(info, 3));
    223231        for (int index = 0; index < count; index++) {
    224             byte[] name = (byte[]) regEnumKeyEx.invoke(root, getNumber(handles, 0), Integer.valueOf(index), Integer.valueOf(maxlen + 1));
     232            byte[] name = (byte[]) REG_ENUM_KEY_EX.invoke(root, getNumber(handles, 0), index, maxlen + 1);
    225233            results.add(new String(name, StandardCharsets.UTF_8).trim());
    226234        }
    227         regCloseKey.invoke(root, getNumber(handles, 0));
     235        REG_CLOSE_KEY.invoke(root, getNumber(handles, 0));
    228236        return Collections.unmodifiableList(results);
    229237    }
Note: See TracChangeset for help on using the changeset viewer.