Hello, good people, For some time, since openjdk was released, we have used as accessibility provider java-atk-wrapper that wraps around the GNOME accessibility toolkit. The java-atk-wrapper is composed from a jar file java-atk-wrapper.jar and a native library libjava-atk-wrapper.so that the java code loads. It was then possible to simply put the java-atk-wrapper.jar into the extension directory and specify in accessibility.properties the class org.GNOME.Accessibility.AtkWrapper as assistive_technologies. The jar file being in extension directory, the class was found and world was wonderful.
What really was wonderful is that the folks that need the accessibility enabled needed only to install a package and the thing was working. There was no need to do any lengthy configuration for them before they could use Java applications. Naturally, this changed when the extension mechanism was discontinued with openjdk9. Moreover, if the class org.GNOME.Accessibility.AtkWrapper is specified in accessibility.properties, but cannot be found, program ends with ClassNotFoundException. Therefore, we tried to add to the accessibility.properties another property, we called it assistive_technologies.classpath, where we specified the place where the jar file was located. Now, we needed to find where one can read the property and how to pass it to the corresponding class loader. First we tried to add this property to the system java.class.path property in java.awt.Toolkit.initAssistiveTechnologies, but it was too late, because the class loaders that use this property have already read it at this time. So, we decided to patch the jdk.internal.loader.ClassLoaders so that this property is considered before the internal class loaders are instantiated. We are reading the assistive_technologies.classpath property from the same files and in the same order as the java.awt.Toolkit.initAssistiveTechnologies does. Besides that, we are checking whether the file that was specified in the property exist in order not to pollute the class path with inexistent elements. If we decided not to do that, the assistive_technologies.classpath could be actually a real class path with several directories/jar files in it. But not sure we want it here. Now, this patch works in the sense that the class is loaded. This brings the org.GNOME.Accessibility.AtkWrapper from a state of being virtually useless to a state where it is loaded as it was with jdk9 and jdk7 before. It also has the advantage of not doing any complicated ugly hacks setting private fields using reflection. Not speaking about the fact that the jdk.internal module is not accessible anyway. I am not sure whether I will be officially and publicly stoned if I propose this upstream. Nevertheless, I would love someone in the know to check the patch, criticize it and propose improvements. I know it is too long to read, but I wanted to give context so that one understands what we are actually trying to achieve. Cheers Fridrich
--- jdk9/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java 2017-10-24 09:33:07.188671701 +0200 +++ jdk9/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java 2017-10-24 14:53:52.881676873 +0200 @@ -26,6 +26,7 @@ package jdk.internal.loader; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.net.URL; import java.nio.file.InvalidPathException; @@ -33,6 +34,7 @@ import java.security.CodeSource; import java.security.PermissionCollection; import java.util.jar.Manifest; +import java.util.Properties; import jdk.internal.misc.JavaLangAccess; import jdk.internal.misc.SharedSecrets; @@ -79,6 +81,59 @@ if (mainMid == null || cp.length() > 0) addClassPathToUCP(cp, ucp); + // Get accessibility properties + final String sep = File.separator; + final Properties properties = new Properties(); + + // Try loading the per-user accessibility properties file. + try { + File propsFile = new File( + System.getProperty("user.home") + + sep + ".accessibility.properties"); + FileInputStream in = + new FileInputStream(propsFile); + + // Inputstream has been buffered in Properties class + properties.load(in); + in.close(); + } catch (Exception e) { + // Per-user accessibility properties file does not exist + } + + // Try loading the system-wide accessibility properties + // file only if a per-user accessibility properties + // file does not exist or is empty. + if (properties.size() == 0) { + try { + File propsFile = new File( + System.getProperty("java.home") + sep + "conf" + + sep + "accessibility.properties"); + FileInputStream in = + new FileInputStream(propsFile); + + // Inputstream has been buffered in Properties class + properties.load(in); + in.close(); + } catch (Exception e) { + // System-wide accessibility properties file does + // not exist; + } + } + + // Add the jar with assistive technologies to the looked up classpath. + final String atCp = properties.getProperty("assistive_technologies.classpath", null); + if (atCp != null) { + File atCpFile = new File(atCp); + if (atCpFile.exists()) { + addClassPathToUCP(atCp, ucp); + if (cp == null || cp.isEmpty()) { + System.setProperty("java.class.path", atCp); + } else { + System.setProperty("java.class.path", cp + System.getProperty("path.separator") + atCp); + } + } + } + // create the class loaders BOOT_LOADER = new BootClassLoader(bcp); PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER);
signature.asc
Description: OpenPGP digital signature