1 /*
2 * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
40 import java.awt.dnd.InvalidDnDOperationException;
41 import java.awt.dnd.peer.DragSourceContextPeer;
42 import java.net.URL;
43 import java.io.File;
44 import java.io.FileInputStream;
45
46 import java.util.*;
47 import java.beans.PropertyChangeListener;
48 import java.beans.PropertyChangeSupport;
49 import sun.awt.AppContext;
50
51 import sun.awt.HeadlessToolkit;
52 import sun.awt.NullComponentPeer;
53 import sun.awt.PeerEvent;
54 import sun.awt.SunToolkit;
55 import sun.awt.AWTAccessor;
56 import sun.awt.AWTPermissions;
57
58 import sun.util.CoreResourceBundleControl;
59
60 /**
61 * This class is the abstract superclass of all actual
62 * implementations of the Abstract Window Toolkit. Subclasses of
63 * the <code>Toolkit</code> class are used to bind the various components
64 * to particular native toolkit implementations.
65 * <p>
66 * Many GUI events may be delivered to user
67 * asynchronously, if the opposite is not specified explicitly.
68 * As well as
69 * many GUI operations may be performed asynchronously.
70 * This fact means that if the state of a component is set, and then
71 * the state immediately queried, the returned value may not yet
72 * reflect the requested change. This behavior includes, but is not
73 * limited to:
74 * <ul>
75 * <li>Scrolling to a specified position.
76 * <br>For example, calling <code>ScrollPane.setScrollPosition</code>
77 * and then <code>getScrollPosition</code> may return an incorrect
78 * value if the original request has not yet been processed.
79 *
737
738 // Inputstream has been buffered in Properties class
739 properties.load(in);
740 in.close();
741 } catch (Exception e) {
742 // System-wide accessibility properties file does
743 // not exist;
744 }
745 }
746
747 // Get whether a screen magnifier is present. First check
748 // the system property and then check the properties file.
749 String magPresent = System.getProperty("javax.accessibility.screen_magnifier_present");
750 if (magPresent == null) {
751 magPresent = properties.getProperty("screen_magnifier_present", null);
752 if (magPresent != null) {
753 System.setProperty("javax.accessibility.screen_magnifier_present", magPresent);
754 }
755 }
756
757 // Get the names of any assistive technolgies to load. First
758 // check the system property and then check the properties
759 // file.
760 String classNames = System.getProperty("javax.accessibility.assistive_technologies");
761 if (classNames == null) {
762 classNames = properties.getProperty("assistive_technologies", null);
763 if (classNames != null) {
764 System.setProperty("javax.accessibility.assistive_technologies", classNames);
765 }
766 }
767 return classNames;
768 }
769 });
770 }
771
772 /**
773 * Loads additional classes into the VM, using the property
774 * 'assistive_technologies' specified in the Sun reference
775 * implementation by a line in the 'accessibility.properties'
776 * file. The form is "assistive_technologies=..." where
777 * the "..." is a comma-separated list of assistive technology
778 * classes to load. Each class is loaded in the order given
779 * and a single instance of each is created using
780 * Class.forName(class).newInstance(). All errors are handled
781 * via an AWTError exception.
782 *
783 * <p>The assumption is made that assistive technology classes are supplied
784 * as part of INSTALLED (as opposed to: BUNDLED) extensions or specified
785 * on the class path
786 * (and therefore can be loaded using the class loader returned by
787 * a call to <code>ClassLoader.getSystemClassLoader</code>, whose
788 * delegation parent is the extension class loader for installed
789 * extensions).
790 */
791 private static void loadAssistiveTechnologies() {
792 // Load any assistive technologies
793 if (atNames != null) {
794 ClassLoader cl = ClassLoader.getSystemClassLoader();
795 StringTokenizer parser = new StringTokenizer(atNames," ,");
796 String atName;
797 while (parser.hasMoreTokens()) {
798 atName = parser.nextToken();
799 try {
800 Class<?> clazz;
801 if (cl != null) {
802 clazz = cl.loadClass(atName);
803 } else {
804 clazz = Class.forName(atName);
805 }
806 clazz.newInstance();
807 } catch (ClassNotFoundException e) {
808 throw new AWTError("Assistive Technology not found: "
809 + atName);
810 } catch (InstantiationException e) {
811 throw new AWTError("Could not instantiate Assistive"
812 + " Technology: " + atName);
813 } catch (IllegalAccessException e) {
814 throw new AWTError("Could not access Assistive"
815 + " Technology: " + atName);
816 } catch (Exception e) {
817 throw new AWTError("Error trying to install Assistive"
818 + " Technology: " + atName + " " + e);
819 }
820 }
821 }
822 }
823
824 /**
825 * Gets the default toolkit.
826 * <p>
827 * If a system property named <code>"java.awt.headless"</code> is set
828 * to <code>true</code> then the headless implementation
829 * of <code>Toolkit</code> is used.
830 * <p>
831 * If there is no <code>"java.awt.headless"</code> or it is set to
832 * <code>false</code> and there is a system property named
833 * <code>"awt.toolkit"</code>,
834 * that property is treated as the name of a class that is a subclass
835 * of <code>Toolkit</code>;
836 * otherwise the default platform-specific implementation of
837 * <code>Toolkit</code> is used.
838 * <p>
839 * Also loads additional classes into the VM, using the property
840 * 'assistive_technologies' specified in the Sun reference
841 * implementation by a line in the 'accessibility.properties'
842 * file. The form is "assistive_technologies=..." where
843 * the "..." is a comma-separated list of assistive technology
844 * classes to load. Each class is loaded in the order given
845 * and a single instance of each is created using
846 * Class.forName(class).newInstance(). This is done just after
847 * the AWT toolkit is created. All errors are handled via an
848 * AWTError exception.
849 * @return the default toolkit.
850 * @exception AWTError if a toolkit could not be found, or
851 * if one could not be accessed or instantiated.
852 */
853 public static synchronized Toolkit getDefaultToolkit() {
854 if (toolkit == null) {
855 java.security.AccessController.doPrivileged(
856 new java.security.PrivilegedAction<Void>() {
857 public Void run() {
858 Class<?> cls = null;
859 String nm = System.getProperty("awt.toolkit");
860 try {
861 cls = Class.forName(nm);
862 } catch (ClassNotFoundException e) {
863 ClassLoader cl = ClassLoader.getSystemClassLoader();
864 if (cl != null) {
865 try {
866 cls = cl.loadClass(nm);
867 } catch (final ClassNotFoundException ignored) {
868 throw new AWTError("Toolkit not found: " + nm);
869 }
870 }
871 }
872 try {
873 if (cls != null) {
874 toolkit = (Toolkit)cls.newInstance();
875 if (GraphicsEnvironment.isHeadless()) {
876 toolkit = new HeadlessToolkit(toolkit);
877 }
878 }
879 } catch (final InstantiationException ignored) {
880 throw new AWTError("Could not instantiate Toolkit: " + nm);
881 } catch (final IllegalAccessException ignored) {
882 throw new AWTError("Could not access Toolkit: " + nm);
883 }
884 return null;
885 }
886 });
887 loadAssistiveTechnologies();
888 }
889 return toolkit;
890 }
891
892 /**
893 * Returns an image which gets pixel data from the specified file,
894 * whose format can be either GIF, JPEG or PNG.
895 * The underlying toolkit attempts to resolve multiple requests
896 * with the same filename to the same returned Image.
897 * <p>
898 * Since the mechanism required to facilitate this sharing of
899 * <code>Image</code> objects may continue to hold onto images
900 * that are no longer in use for an indefinite period of time,
901 * developers are encouraged to implement their own caching of
902 * images by using the {@link #createImage(java.lang.String) createImage}
903 * variant wherever available.
904 * If the image data contained in the specified file changes,
905 * the <code>Image</code> object returned from this method may
906 * still contain stale information which was loaded from the
907 * file after a prior call.
|
1 /*
2 * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
40 import java.awt.dnd.InvalidDnDOperationException;
41 import java.awt.dnd.peer.DragSourceContextPeer;
42 import java.net.URL;
43 import java.io.File;
44 import java.io.FileInputStream;
45
46 import java.util.*;
47 import java.beans.PropertyChangeListener;
48 import java.beans.PropertyChangeSupport;
49 import sun.awt.AppContext;
50
51 import sun.awt.HeadlessToolkit;
52 import sun.awt.NullComponentPeer;
53 import sun.awt.PeerEvent;
54 import sun.awt.SunToolkit;
55 import sun.awt.AWTAccessor;
56 import sun.awt.AWTPermissions;
57
58 import sun.util.CoreResourceBundleControl;
59
60 import java.security.AccessController;
61 import java.security.PrivilegedAction;
62 import java.util.ServiceLoader;
63 import java.util.stream.Collectors;
64 import javax.accessibility.AccessibilitySPI;
65 /**
66 * This class is the abstract superclass of all actual
67 * implementations of the Abstract Window Toolkit. Subclasses of
68 * the <code>Toolkit</code> class are used to bind the various components
69 * to particular native toolkit implementations.
70 * <p>
71 * Many GUI events may be delivered to user
72 * asynchronously, if the opposite is not specified explicitly.
73 * As well as
74 * many GUI operations may be performed asynchronously.
75 * This fact means that if the state of a component is set, and then
76 * the state immediately queried, the returned value may not yet
77 * reflect the requested change. This behavior includes, but is not
78 * limited to:
79 * <ul>
80 * <li>Scrolling to a specified position.
81 * <br>For example, calling <code>ScrollPane.setScrollPosition</code>
82 * and then <code>getScrollPosition</code> may return an incorrect
83 * value if the original request has not yet been processed.
84 *
742
743 // Inputstream has been buffered in Properties class
744 properties.load(in);
745 in.close();
746 } catch (Exception e) {
747 // System-wide accessibility properties file does
748 // not exist;
749 }
750 }
751
752 // Get whether a screen magnifier is present. First check
753 // the system property and then check the properties file.
754 String magPresent = System.getProperty("javax.accessibility.screen_magnifier_present");
755 if (magPresent == null) {
756 magPresent = properties.getProperty("screen_magnifier_present", null);
757 if (magPresent != null) {
758 System.setProperty("javax.accessibility.screen_magnifier_present", magPresent);
759 }
760 }
761
762 // Get the names of any assistive technologies to load. First
763 // check the system property and then check the properties
764 // file.
765 String classNames = System.getProperty("javax.accessibility.assistive_technologies");
766 if (classNames == null) {
767 classNames = properties.getProperty("assistive_technologies", null);
768 if (classNames != null) {
769 System.setProperty("javax.accessibility.assistive_technologies", classNames);
770 }
771 }
772 return classNames;
773 }
774 });
775 }
776
777 /**
778 * Rethrow the AWTError but include the cause.
779 *
780 * @param s the error message
781 * @param e the original exception
782 * @throw the new AWTError including the cause (the original exception)
783 */
784 private static void newAWTError(Throwable e, String s) {
785 AWTError newAWTError = new AWTError(s);
786 newAWTError.initCause(e);
787 throw newAWTError;
788 }
789
790 /**
791 * When a service provider for Assistive Technology is not found look for a
792 * supporting class on the class path and instantiate it.
793 *
794 * @param atName the name of the class to be loaded
795 */
796 private static void fallbackToLoadClassForAT(String atName) {
797 ClassLoader cl = ClassLoader.getSystemClassLoader();
798 try {
799 Class<?> clazz;
800 if (cl != null) {
801 clazz = cl.loadClass(atName);
802 } else {
803 clazz = Class.forName(atName);
804 }
805 clazz.newInstance();
806 } catch (ClassNotFoundException e) {
807 newAWTError(e, "Assistive Technology not found: " + atName);
808 } catch (InstantiationException e) {
809 newAWTError(e, "Could not instantiate Assistive Technology: " + atName);
810 } catch (IllegalAccessException e) {
811 newAWTError(e, "Could not access Assistive Technology: " + atName);
812 } catch (Exception e) {
813 newAWTError(e, "Error trying to install Assistive Technology: " + atName);
814 }
815 }
816
817 /**
818 * Loads additional classes into the VM, using the property
819 * 'assistive_technologies' specified in the Sun reference
820 * implementation by a line in the 'accessibility.properties'
821 * file. The form is "assistive_technologies=..." where
822 * the "..." is a comma-separated list of assistive technology
823 * classes to load. Each class is loaded in the order given
824 * and a single instance of each is created using
825 * Class.forName(class).newInstance(). All errors are handled
826 * via an AWTError exception.
827 *
828 * <p>The assumption is made that assistive technology classes are supplied
829 * as part of INSTALLED (as opposed to: BUNDLED) extensions or specified
830 * on the class path
831 * (and therefore can be loaded using the class loader returned by
832 * a call to {@code ClassLoader.getSystemClassLoader}, whose
833 * delegation parent is the extension class loader for installed
834 * extensions).
835 */
836 private static void loadAssistiveTechnologies() {
837 // Load any assistive technologies
838 if (atNames != null) {
839 ClassLoader cl = ClassLoader.getSystemClassLoader();
840 Set<String> names = Arrays.stream(atNames.split(","))
841 .map(String::trim)
842 .collect(Collectors.toSet());
843 final Map<String, AccessibilitySPI> providers = new HashMap<>();
844 AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
845 for (AccessibilitySPI p : ServiceLoader.load(AccessibilitySPI.class, cl)) {
846 String name = p.name();
847 if (names.contains(name) && !providers.containsKey(name)) {
848 p.activate();
849 providers.put(name, p);
850 }
851 }
852 return null;
853 });
854 names.stream()
855 .filter(n -> !providers.containsKey(n))
856 .forEach(Toolkit::fallbackToLoadClassForAT);
857 }
858 }
859
860 /**
861 * Gets the default toolkit.
862 * <p>
863 * If a system property named {@code "java.awt.headless"} is set
864 * to {@code true} then the headless implementation
865 * of {@code Toolkit} is used.
866 * <p>
867 * If there is no {@code "java.awt.headless"} or it is set to
868 * {@code false} and there is a system property named
869 * {@code "awt.toolkit"},
870 * that property is treated as the name of a class that is a subclass
871 * of {@code Toolkit};
872 * otherwise the default platform-specific implementation of
873 * {@code Toolkit} is used.
874 * <p>
875 * If this Toolkit is not a headless implementation and if they exist, service
876 * providers of {@link javax.accessibility.AccessibilitySPI} will be loaded
877 * if specified by the system property
878 * {@code javax.accessibility.assistive_technologies}.
879 * <p>
880 * An example of setting this property is to invoke Java with
881 * {@code -Djavax.accessibility.assistive_technologies=MyServiceProvider}.
882 * In addition to MyServiceProvider other service providers can be specified
883 * using a comma separated list. Service providers are loaded after the AWT
884 * toolkit is created. All errors are handled via an AWTError exception.
885 * <p>
886 * The service providers have two methods,
887 * {@link javax.accessibility.AccessibilitySPI#name name} and
888 * {@link javax.accessibility.AccessibilitySPI#activate activate}. The names
889 * specified in the assistive_technologies property are used to query each
890 * service provider implementation. If the requested name matches the name
891 * of the service provider, the {@code activate} method will be invoked to
892 * activate the matching service provider.
893 *
894 * @implNote
895 * If assistive technology service providers are not specified with a system
896 * property this implementation will fall back to looking in a properties file
897 * located as follows:
898 * <ul>
899 * <li> {@code ${user.home}/.accessibility.properties}
900 * <li> {@code ${java.home}/conf/accessibility.properties}
901 * </ul>
902 * Only the first of these files to be located will be consulted. The requested
903 * service providers are specified by setting the {@code assistive_technologies=}
904 * property. A single provider or a comma separated list of providers can be
905 * specified.
906 * <p>
907 * Assistive technology service providers can be created as follows:
908 * <ul>
909 * <li>Create a subclass of {@code javax.accessibility.AccessibilitySPI},
910 * for example, {@code my.package.ProviderImpl}.
911 * <li>Add a {@code META-INF/services} directory as a sibling directory
912 * to the top level directory which contains the implementation.
913 * <li>In that directory create the file
914 * {@code META-INF/services/javax.accessibility.AccessibilitySPI}
915 * containing the package name of the implementation, for example,
916 * {@code my.package.ProviderImpl}.
917 * </ul>
918 *
919 * @return the default toolkit.
920 * @exception AWTError if a toolkit could not be found, or
921 * if one could not be accessed or instantiated.
922 * @see javax.accessibility.AccessibilitySPI
923 */
924 public static synchronized Toolkit getDefaultToolkit() {
925 if (toolkit == null) {
926 java.security.AccessController.doPrivileged(
927 new java.security.PrivilegedAction<Void>() {
928 public Void run() {
929 Class<?> cls = null;
930 String nm = System.getProperty("awt.toolkit");
931 try {
932 cls = Class.forName(nm);
933 } catch (ClassNotFoundException e) {
934 ClassLoader cl = ClassLoader.getSystemClassLoader();
935 if (cl != null) {
936 try {
937 cls = cl.loadClass(nm);
938 } catch (final ClassNotFoundException ignored) {
939 throw new AWTError("Toolkit not found: " + nm);
940 }
941 }
942 }
943 try {
944 if (cls != null) {
945 toolkit = (Toolkit)cls.newInstance();
946 if (GraphicsEnvironment.isHeadless()) {
947 toolkit = new HeadlessToolkit(toolkit);
948 }
949 }
950 } catch (final InstantiationException ignored) {
951 throw new AWTError("Could not instantiate Toolkit: " + nm);
952 } catch (final IllegalAccessException ignored) {
953 throw new AWTError("Could not access Toolkit: " + nm);
954 }
955 return null;
956 }
957 });
958 if (!GraphicsEnvironment.isHeadless()) {
959 loadAssistiveTechnologies();
960 }
961 }
962 return toolkit;
963 }
964
965 /**
966 * Returns an image which gets pixel data from the specified file,
967 * whose format can be either GIF, JPEG or PNG.
968 * The underlying toolkit attempts to resolve multiple requests
969 * with the same filename to the same returned Image.
970 * <p>
971 * Since the mechanism required to facilitate this sharing of
972 * <code>Image</code> objects may continue to hold onto images
973 * that are no longer in use for an indefinite period of time,
974 * developers are encouraged to implement their own caching of
975 * images by using the {@link #createImage(java.lang.String) createImage}
976 * variant wherever available.
977 * If the image data contained in the specified file changes,
978 * the <code>Image</code> object returned from this method may
979 * still contain stale information which was loaded from the
980 * file after a prior call.
|