--- old/src/java.desktop/share/classes/java/awt/Toolkit.java 2015-03-19 19:57:40.338262300 -0500 +++ new/src/java.desktop/share/classes/java/awt/Toolkit.java 2015-03-19 19:57:39.741228200 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,6 +57,11 @@ import sun.util.CoreResourceBundleControl; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ServiceLoader; +import java.util.stream.Collectors; +import javax.accessibility.AccessibilityProvider; /** * This class is the abstract superclass of all actual * implementations of the Abstract Window Toolkit. Subclasses of @@ -754,7 +759,7 @@ } } - // Get the names of any assistive technolgies to load. First + // Get the names of any assistive technologies to load. First // check the system property and then check the properties // file. String classNames = System.getProperty("javax.accessibility.assistive_technologies"); @@ -770,85 +775,135 @@ } /** - * Loads additional classes into the VM, using the property - * 'assistive_technologies' specified in the Sun reference - * implementation by a line in the 'accessibility.properties' - * file. The form is "assistive_technologies=..." where - * the "..." is a comma-separated list of assistive technology - * classes to load. Each class is loaded in the order given - * and a single instance of each is created using - * Class.forName(class).newInstance(). All errors are handled - * via an AWTError exception. + * Rethrow the AWTError but include the cause. + * + * @param s the error message + * @param e the original exception + * @throw the new AWTError including the cause (the original exception) + */ + private static void newAWTError(Throwable e, String s) { + AWTError newAWTError = new AWTError(s); + newAWTError.initCause(e); + throw newAWTError; + } + + /** + * When a service provider for Assistive Technology is not found look for a + * supporting class on the class path and instantiate it. + * + * @param atName the name of the class to be loaded + */ + private static void fallbackToLoadClassForAT(String atName) { + try { + Class.forName(atName, false, ClassLoader.getSystemClassLoader()).newInstance(); + } catch (ClassNotFoundException e) { + newAWTError(e, "Assistive Technology not found: " + atName); + } catch (InstantiationException e) { + newAWTError(e, "Could not instantiate Assistive Technology: " + atName); + } catch (IllegalAccessException e) { + newAWTError(e, "Could not access Assistive Technology: " + atName); + } catch (Exception e) { + newAWTError(e, "Error trying to install Assistive Technology: " + atName); + } + } + + /** + * Loads accessibility support using the property assistive_technologies. + * The form is assistive_technologies= followed by a comma-separated list of + * assistive technology providers to load. The order in which providers are + * loaded is determined by the order in which the ServiceLoader discovers + * implementations of the AccessibilityProvider interface, not by the order + * of provider names in the property list. When a provider is found its + * accessibility implementation will be started by calling the provider's + * activate method. All errors are handled via an AWTError exception. * - *
The assumption is made that assistive technology classes are supplied
- * as part of INSTALLED (as opposed to: BUNDLED) extensions or specified
- * on the class path
- * (and therefore can be loaded using the class loader returned by
- * a call to
- * If a system property named
- * If there is no
+ * If this Toolkit is not a headless implementation and if they exist, service
+ * providers of {@link javax.accessibility.AccessibilityProvider} will be loaded
+ * if specified by the system property
+ * {@code javax.accessibility.assistive_technologies}.
+ *
+ * An example of setting this property is to invoke Java with
+ * {@code -Djavax.accessibility.assistive_technologies=MyServiceProvider}.
+ * In addition to MyServiceProvider other service providers can be specified
+ * using a comma separated list. Service providers are loaded after the AWT
+ * toolkit is created. All errors are handled via an AWTError exception.
*
- * Also loads additional classes into the VM, using the property
- * 'assistive_technologies' specified in the Sun reference
- * implementation by a line in the 'accessibility.properties'
- * file. The form is "assistive_technologies=..." where
- * the "..." is a comma-separated list of assistive technology
- * classes to load. Each class is loaded in the order given
- * and a single instance of each is created using
- * Class.forName(class).newInstance(). This is done just after
- * the AWT toolkit is created. All errors are handled via an
- * AWTError exception.
+ * The names specified in the assistive_technologies property are used to query
+ * each service provider implementation. If the requested name matches the
+ * {@linkplain AccessibilityProvider#name name} of the service provider, the
+ * {@link AccessibilityProvider#activate} method will be invoked to activate the
+ * matching service provider.
+ *
+ * @implSpec
+ * If assistive technology service providers are not specified with a system
+ * property this implementation will look in a properties file located as follows:
+ *
+ * Assistive technology service providers can be created as follows:
+ *
+ * This service provider class provides mappings from the platform
+ * specific accessibility APIs to the Java Accessibility API.
+ *
+ * Each service provider implementation is named and can be activated via the
+ * {@link #activate} method. Service providers can be loaded when the default
+ * {@link java.awt.Toolkit toolkit} is initialized.
+ *
+ * @apiNote There will typically be one provider per platform, such as Windows
+ * or Linux, to support accessibility for screen readers and magnifiers. However,
+ * more than one service provider can be activated. For example, a test tool
+ * which provides visual results obtained by interrogating the Java Accessibility
+ * API can be activated along with the activation of the support for screen readers
+ * and screen magnifiers.
+ *
+ * @see java.awt.Toolkit#getDefaultToolkit
+ * @see java.util.ServiceLoader
+ * @since 1.9
+ */
+public abstract class AccessibilityProvider {
+
+
+ /**
+ * Initializes a new accessibility provider.
+ *
+ * @throws SecurityException
+ * If a security manager has been installed and it denies
+ * {@link RuntimePermission}{@code("accessibilityProvider")}
+ */
+ protected AccessibilityProvider() {
+ // Use a permission check when calling a private constructor to check that
+ // the proper security permission has been granted before the Object superclass
+ // is called. If an exception is thrown before the Object superclass is
+ // constructed a finalizer in a subclass of this class will not be run.
+ // This protects against a finalizer vulnerability.
+ this(checkPermission());
+ }
+
+ private AccessibilityProvider(Void ignore) { }
+
+ /**
+ * If this code is running with a security manager and if the permission
+ * "accessibilityProvider" has not been granted SecurityException will be thrown.
+ *
+ */
+ private static Void checkPermission() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new RuntimePermission("accessibilityProvider"));
+ return null;
+ }
+
+ /**
+ * Returns the name of this service provider. This name is used to locate a
+ * requested service provider.
+ *
+ * @return the name of this service provider
+ */
+ public abstract String name();
+
+ /**
+ * Activates the support provided by this service provider.
+ */
+ public abstract void activate();
+}
--- /dev/null 2015-03-19 19:57:49.000000000 -0500
+++ new/test/javax/accessibility/AccessibilityProvider/BarProvider.java 2015-03-19 19:57:48.703740800 -0500
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.accessibility.AccessibilityProvider;
+
+public final class BarProvider extends AccessibilityProvider {
+ private final String name = "BarProvider";
+
+ public BarProvider() {}
+
+ public String name() {
+ return name;
+ }
+
+ public void activate() {
+ // raise an exception so we'll know that start was called
+ throw new RuntimeException("ProviderStarted");
+ }
+
+}
--- /dev/null 2015-03-19 19:57:54.000000000 -0500
+++ new/test/javax/accessibility/AccessibilityProvider/FooProvider.java 2015-03-19 19:57:52.800975100 -0500
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.accessibility.AccessibilityProvider;
+
+public final class FooProvider extends AccessibilityProvider {
+ private final String name = "FooProvider";
+
+ public FooProvider() {}
+
+ public String name() {
+ return name;
+ }
+
+ public void activate() {
+ // raise an exception so we'll know that start was called
+ throw new RuntimeException("ProviderStarted");
+ }
+
+}
--- /dev/null 2015-03-19 19:57:58.000000000 -0500
+++ new/test/javax/accessibility/AccessibilityProvider/Load.java 2015-03-19 19:57:57.430239900 -0500
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//
+
+import java.awt.Toolkit;
+import java.awt.AWTError;
+
+public class Load {
+
+ public static void main(String[] args) {
+ try {
+ Toolkit.getDefaultToolkit();
+ } catch (RuntimeException e) {
+ // See if the activate method was called
+ if (!e.getMessage().equals("ProviderStarted")) {
+ throw e;
+ }
+ } catch (AWTError e) {
+ if (!args[0].equals("fail")) {
+ throw e;
+ }
+ }
+ }
+
+}
--- /dev/null 2015-03-19 19:58:02.000000000 -0500
+++ new/test/javax/accessibility/AccessibilityProvider/UnusedProvider.java 2015-03-19 19:58:01.596478200 -0500
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.accessibility.AccessibilityProvider;
+
+public final class UnusedProvider extends AccessibilityProvider {
+ private final String name = "UnusedProvider";
+
+ public UnusedProvider() {}
+
+ public String name() {
+ return name;
+ }
+
+ public void activate() {
+ // raise an exception; this method shouldn't be called
+ throw new RuntimeException("UnusedProviderStarted");
+ }
+
+}
--- /dev/null 2015-03-19 19:58:07.000000000 -0500
+++ new/test/javax/accessibility/AccessibilityProvider/accessibilityProvider.sp 2015-03-19 19:58:05.921725600 -0500
@@ -0,0 +1,3 @@
+grant {
+ permission java.lang.RuntimePermission "accessibilityProvider";
+};
--- /dev/null 2015-03-19 19:58:11.000000000 -0500
+++ new/test/javax/accessibility/AccessibilityProvider/basic.sh 2015-03-19 19:58:10.597993100 -0500
@@ -0,0 +1,99 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+# @test
+# @bug 8055160
+# @summary Unit test for javax.accessibility.AccessibilitySPI
+#
+# @build Load FooProvider
+# @build Load BarProvider
+# @build Load UnusedProvider
+# @run shell basic.sh
+#
+# Command-line usage: sh basic.sh /path/to/build
+
+if [ -z "$TESTJAVA" ]; then
+ if [ $# -lt 1 ]; then exit 1; fi
+ TESTJAVA="$1"
+ TESTSRC=`pwd`
+ TESTCLASSES="`pwd`"
+fi
+
+JAVA="$TESTJAVA/bin/java"
+
+OS=`uname -s`
+case "$OS" in
+ SunOS | Darwin | AIX )
+ FS='/'
+ SEP=':' ;;
+ Linux )
+ FS='/'
+ SEP=':' ;;
+ * )
+ FS='\\'
+ SEP='\;' ;;
+esac
+
+TESTD=x.test
+rm -rf $TESTD
+mkdir -p $TESTD
+
+mv $TESTCLASSES/FooProvider.class $TESTD
+mv $TESTCLASSES/BarProvider.class $TESTD
+mv $TESTCLASSES/UnusedProvider.class $TESTD
+mkdir -p $TESTD/META-INF/services
+echo FooProvider >$TESTD/META-INF/services/javax.accessibility.AccessibilityProvider
+echo BarProvider >>$TESTD/META-INF/services/javax.accessibility.AccessibilityProvider
+echo UnusedProvider >>$TESTD/META-INF/services/javax.accessibility.AccessibilityProvider
+
+
+failures=0
+
+go() {
+ echo ''
+ CP="$TESTCLASSES$SEP$TESTD"
+ sh -xc "'$JAVA' $SECURITY_MANAGER $PROVIDER $TESTVMOPTS -cp $CP Load $1" 2>&1
+ if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
+}
+
+# find one provider
+PROVIDER="-Djavax.accessibility.assistive_technologies=FooProvider"
+go
+
+# find two providers
+PROVIDER="-Djavax.accessibility.assistive_technologies=FooProvider,BarProvider"
+go
+
+#find provider, using security manager
+SECURITY_MANAGER="-Djava.security.manager -Djava.security.policy==$TESTSRC/accessibilityProvider.sp"
+go
+
+#fail if no provider
+PROVIDER="-Djavax.accessibility.assistive_technologies=NoProvider"
+go fail
+
+echo ''
+if [ $failures -gt 0 ];
+ then echo "$failures case(s) failed";
+ else echo "All cases passed"; fi
+exit $failures
+
ClassLoader.getSystemClassLoader
, whose
- * delegation parent is the extension class loader for installed
- * extensions).
+ * The assumption is made that assistive technology providers are supplied
+ * as part of java.desktop module or specified on the classpath.
*/
private static void loadAssistiveTechnologies() {
// Load any assistive technologies
if (atNames != null) {
ClassLoader cl = ClassLoader.getSystemClassLoader();
- StringTokenizer parser = new StringTokenizer(atNames," ,");
- String atName;
- while (parser.hasMoreTokens()) {
- atName = parser.nextToken();
- try {
- Class> clazz;
- if (cl != null) {
- clazz = cl.loadClass(atName);
- } else {
- clazz = Class.forName(atName);
+ Set"java.awt.headless"
is set
- * to true
then the headless implementation
- * of Toolkit
is used.
+ * If a system property named {@code "java.awt.headless"} is set
+ * to {@code true} then the headless implementation
+ * of {@code Toolkit} is used.
* "java.awt.headless"
or it is set to
- * false
and there is a system property named
- * "awt.toolkit"
,
+ * If there is no {@code "java.awt.headless"} or it is set to
+ * {@code false} and there is a system property named
+ * {@code "awt.toolkit"},
* that property is treated as the name of a class that is a subclass
- * of Toolkit
;
+ * of {@code Toolkit};
* otherwise the default platform-specific implementation of
- * Toolkit
is used.
+ * {@code Toolkit} is used.
+ *
+ *
+ * Only the first of these files to be located will be consulted. The requested
+ * service providers are specified by setting the {@code assistive_technologies=}
+ * property. A single provider or a comma separated list of providers can be
+ * specified.
+ *
+ *
+ *
* @return the default toolkit.
* @exception AWTError if a toolkit could not be found, or
* if one could not be accessed or instantiated.
+ * @see javax.accessibility.AccessibilityProvider
*/
public static synchronized Toolkit getDefaultToolkit() {
if (toolkit == null) {
@@ -884,7 +939,9 @@
return null;
}
});
- loadAssistiveTechnologies();
+ if (!GraphicsEnvironment.isHeadless()) {
+ loadAssistiveTechnologies();
+ }
}
return toolkit;
}
--- /dev/null 2015-03-19 19:57:46.000000000 -0500
+++ new/src/java.desktop/share/classes/javax/accessibility/AccessibilityProvider.java 2015-03-19 19:57:44.910523800 -0500
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.accessibility;
+
+/**
+ * Service Provider Interface (SPI) for Assistive Technology.
+ *