Changeset 13651 in josm


Ignore:
Timestamp:
2018-04-20T21:57:25+02:00 (18 months ago)
Author:
Don-vip
Message:

see #16047 - make WinRegistry class work both with Java 8 and 11

Location:
trunk/src/org/openstreetmap/josm
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/MainApplication.java

    r13647 r13651  
    11591159                platform.getDefaultStyle().equals(LafPreference.LAF.get())) {
    11601160            try {
    1161                 final int currentBuild = Integer.parseInt(PlatformHookWindows.getCurrentBuild());
    1162                 final int javaVersion = Utils.getJavaVersion();
    1163                 final int javaUpdate = Utils.getJavaUpdate();
    1164                 final int javaBuild = Utils.getJavaBuild();
    1165                 // See https://technet.microsoft.com/en-us/windows/release-info.aspx
    1166                 if (currentBuild >= 15_063 && ((javaVersion == 8 && javaUpdate < 141)
    1167                         || (javaVersion == 9 && javaUpdate == 0 && javaBuild < 173))) {
    1168                     // Workaround from https://bugs.openjdk.java.net/browse/JDK-8179014
    1169                     UIManager.put("FileChooser.useSystemExtensionHiding", Boolean.FALSE);
     1161                String build = PlatformHookWindows.getCurrentBuild();
     1162                if (build != null) {
     1163                    final int currentBuild = Integer.parseInt(build);
     1164                    final int javaVersion = Utils.getJavaVersion();
     1165                    final int javaUpdate = Utils.getJavaUpdate();
     1166                    final int javaBuild = Utils.getJavaBuild();
     1167                    // See https://technet.microsoft.com/en-us/windows/release-info.aspx
     1168                    if (currentBuild >= 15_063 && ((javaVersion == 8 && javaUpdate < 141)
     1169                            || (javaVersion == 9 && javaUpdate == 0 && javaBuild < 173))) {
     1170                        // Workaround from https://bugs.openjdk.java.net/browse/JDK-8179014
     1171                        UIManager.put("FileChooser.useSystemExtensionHiding", Boolean.FALSE);
     1172                    }
    11701173                }
    11711174            } catch (NumberFormatException | ReflectiveOperationException | JosmRuntimeException e) {
  • trunk/src/org/openstreetmap/josm/tools/WinRegistry.java

    r12887 r13651  
    4141    public static final int HKEY_LOCAL_MACHINE = 0x80000002;
    4242
    43     private static final int REG_SUCCESS = 0;
     43    private static final long REG_SUCCESS = 0L;
    4444
    4545    private static final int KEY_READ = 0x20019;
     
    5454    private static final Method regEnumKeyEx;
    5555
     56    private static boolean java11;
     57
    5658    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        Utils.setObjectsAccessible(regOpenKey, regCloseKey, regQueryValueEx, regEnumValue, regQueryInfoKey, regEnumKeyEx);
     66    }
     67
     68    private static Method getDeclaredMethod(String name, Class<?>... parameterTypes) {
    5769        try {
    58             regOpenKey = userClass.getDeclaredMethod("WindowsRegOpenKey", int.class, byte[].class, int.class);
    59             regCloseKey = userClass.getDeclaredMethod("WindowsRegCloseKey", int.class);
    60             regQueryValueEx = userClass.getDeclaredMethod("WindowsRegQueryValueEx", int.class, byte[].class);
    61             regEnumValue = userClass.getDeclaredMethod("WindowsRegEnumValue", int.class, int.class, int.class);
    62             regQueryInfoKey = userClass.getDeclaredMethod("WindowsRegQueryInfoKey1", int.class);
    63             regEnumKeyEx = userClass.getDeclaredMethod("WindowsRegEnumKeyEx", int.class, int.class, int.class);
    64             Utils.setObjectsAccessible(regOpenKey, regCloseKey, regQueryValueEx, regEnumValue, regQueryInfoKey, regEnumKeyEx);
    65         } catch (RuntimeException | ReflectiveOperationException e) {
    66             throw new JosmRuntimeException(e);
    67         }
     70            return userClass.getDeclaredMethod(name, parameterTypes);
     71        } 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            }
     79            Logging.log(Logging.LEVEL_ERROR, "Unable to find WindowsReg method", e);
     80            return null;
     81        } catch (RuntimeException e) {
     82            Logging.log(Logging.LEVEL_ERROR, "Unable to get WindowsReg method", e);
     83            return null;
     84        }
     85    }
     86
     87    private static Number hkey(int key) {
     88        return java11 ? ((Number) Long.valueOf(key)) : ((Number) Integer.valueOf(key));
    6889    }
    6990
     
    135156    // =====================
    136157
     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[]) {
     162            return ((long[]) array)[index];
     163        }
     164        throw new IllegalArgumentException();
     165    }
     166
    137167    private static String readString(Preferences root, int hkey, String key, String value)
    138168            throws IllegalAccessException, InvocationTargetException {
    139         int[] handles = (int[]) regOpenKey.invoke(root, Integer.valueOf(hkey), toCstr(key), Integer.valueOf(KEY_READ));
    140         if (handles[1] != REG_SUCCESS) {
    141             return null;
    142         }
    143         byte[] valb = (byte[]) regQueryValueEx.invoke(root, Integer.valueOf(handles[0]), toCstr(value));
    144         regCloseKey.invoke(root, Integer.valueOf(handles[0]));
     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));
    145179        return (valb != null ? new String(valb, StandardCharsets.UTF_8).trim() : null);
    146180    }
     
    148182    private static Map<String, String> readStringValues(Preferences root, int hkey, String key)
    149183            throws IllegalAccessException, InvocationTargetException {
     184        if (regOpenKey == null || regQueryInfoKey == null || regEnumValue == null || regCloseKey == null) {
     185            return null;
     186        }
    150187        HashMap<String, String> results = new HashMap<>();
    151         int[] handles = (int[]) regOpenKey.invoke(root, Integer.valueOf(hkey), toCstr(key), Integer.valueOf(KEY_READ));
    152         if (handles[1] != REG_SUCCESS) {
    153             return null;
    154         }
    155         int[] info = (int[]) regQueryInfoKey.invoke(root, Integer.valueOf(handles[0]));
    156 
    157         int count = info[0]; // count
    158         int maxlen = info[3]; // value length max
     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) {
     191            return null;
     192        }
     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();
    159198        for (int index = 0; index < count; index++) {
    160             byte[] name = (byte[]) regEnumValue.invoke(root, Integer.valueOf(handles[0]), Integer.valueOf(index), Integer.valueOf(maxlen + 1));
     199            byte[] name = (byte[]) regEnumValue.invoke(root, getNumber(handles, 0), Integer.valueOf(index), Integer.valueOf(maxlen + 1));
    161200            String value = readString(hkey, key, new String(name, StandardCharsets.UTF_8));
    162201            results.put(new String(name, StandardCharsets.UTF_8).trim(), value);
    163202        }
    164         regCloseKey.invoke(root, Integer.valueOf(handles[0]));
     203        regCloseKey.invoke(root, getNumber(handles, 0));
    165204        return results;
    166205    }
     
    168207    private static List<String> readStringSubKeys(Preferences root, int hkey, String key)
    169208            throws IllegalAccessException, InvocationTargetException {
     209        if (regOpenKey == null || regQueryInfoKey == null || regEnumKeyEx == null || regCloseKey == null) {
     210            return null;
     211        }
    170212        List<String> results = new ArrayList<>();
    171         int[] handles = (int[]) regOpenKey.invoke(root, Integer.valueOf(hkey), toCstr(key), Integer.valueOf(KEY_READ));
    172         if (handles[1] != REG_SUCCESS) {
     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) {
    173216            return Collections.emptyList();
    174217        }
    175         int[] info = (int[]) regQueryInfoKey.invoke(root, Integer.valueOf(handles[0]));
    176 
    177         int count = info[0]; // Fix: info[2] was being used here with wrong results. Suggested by davenpcj, confirmed by Petrucio
    178         int maxlen = info[3]; // value length max
     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();
    179223        for (int index = 0; index < count; index++) {
    180             byte[] name = (byte[]) regEnumKeyEx.invoke(root, Integer.valueOf(handles[0]), Integer.valueOf(index), Integer.valueOf(maxlen + 1));
     224            byte[] name = (byte[]) regEnumKeyEx.invoke(root, getNumber(handles, 0), Integer.valueOf(index), Integer.valueOf(maxlen + 1));
    181225            results.add(new String(name, StandardCharsets.UTF_8).trim());
    182226        }
    183         regCloseKey.invoke(root, Integer.valueOf(handles[0]));
     227        regCloseKey.invoke(root, getNumber(handles, 0));
    184228        return results;
    185229    }
Note: See TracChangeset for help on using the changeset viewer.