Merge
This commit is contained in:
commit
8a05f12710
@ -21,4 +21,4 @@
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
tzdata2016d
|
||||
tzdata2016f
|
||||
|
@ -366,6 +366,12 @@ Rule Egypt 2007 only - Sep Thu>=1 24:00 0 -
|
||||
# decision to abandon DST permanently. See Ahram Online 2015-04-24.
|
||||
# http://english.ahram.org.eg/NewsContent/1/64/128509/Egypt/Politics-/Sisi-cancels-daylight-saving-time-in-Egypt.aspx
|
||||
|
||||
# From Steffen Thorsen (2016-04-29):
|
||||
# Egypt will have DST from July 7 until the end of October....
|
||||
# http://english.ahram.org.eg/NewsContentP/1/204655/Egypt/Daylight-savings-time-returning-to-Egypt-on--July.aspx
|
||||
# From Mina Samuel (2016-07-04):
|
||||
# Egyptian government took the decision to cancel the DST,
|
||||
|
||||
Rule Egypt 2008 only - Aug lastThu 24:00 0 -
|
||||
Rule Egypt 2009 only - Aug 20 24:00 0 -
|
||||
Rule Egypt 2010 only - Aug 10 24:00 0 -
|
||||
@ -881,11 +887,11 @@ Rule Morocco 2009 only - Aug 21 0:00 0 -
|
||||
Rule Morocco 2010 only - May 2 0:00 1:00 S
|
||||
Rule Morocco 2010 only - Aug 8 0:00 0 -
|
||||
Rule Morocco 2011 only - Apr 3 0:00 1:00 S
|
||||
Rule Morocco 2011 only - Jul 31 0 0 -
|
||||
Rule Morocco 2011 only - Jul 31 0:00 0 -
|
||||
Rule Morocco 2012 2013 - Apr lastSun 2:00 1:00 S
|
||||
Rule Morocco 2012 only - Sep 30 3:00 0 -
|
||||
Rule Morocco 2012 only - Jul 20 3:00 0 -
|
||||
Rule Morocco 2012 only - Aug 20 2:00 1:00 S
|
||||
Rule Morocco 2012 only - Sep 30 3:00 0 -
|
||||
Rule Morocco 2013 only - Jul 7 3:00 0 -
|
||||
Rule Morocco 2013 only - Aug 10 2:00 1:00 S
|
||||
Rule Morocco 2013 max - Oct lastSun 3:00 0 -
|
||||
|
@ -36,7 +36,7 @@
|
||||
#
|
||||
# Except for the French entries,
|
||||
# I made up all time zone abbreviations mentioned here; corrections welcome!
|
||||
# FORMAT is 'zzz' and GMTOFF is 0 for locations while uninhabited.
|
||||
# FORMAT is '-00' and GMTOFF is 0 for locations while uninhabited.
|
||||
|
||||
# Argentina - year-round bases
|
||||
# Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
|
||||
@ -90,22 +90,22 @@
|
||||
# http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
|
||||
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone Antarctica/Casey 0 - zzz 1969
|
||||
Zone Antarctica/Casey 0 - -00 1969
|
||||
8:00 - AWST 2009 Oct 18 2:00
|
||||
# Australian Western Std Time
|
||||
11:00 - CAST 2010 Mar 5 2:00 # Casey Time
|
||||
8:00 - AWST 2011 Oct 28 2:00
|
||||
11:00 - CAST 2012 Feb 21 17:00u
|
||||
8:00 - AWST
|
||||
Zone Antarctica/Davis 0 - zzz 1957 Jan 13
|
||||
Zone Antarctica/Davis 0 - -00 1957 Jan 13
|
||||
7:00 - DAVT 1964 Nov # Davis Time
|
||||
0 - zzz 1969 Feb
|
||||
0 - -00 1969 Feb
|
||||
7:00 - DAVT 2009 Oct 18 2:00
|
||||
5:00 - DAVT 2010 Mar 10 20:00u
|
||||
7:00 - DAVT 2011 Oct 28 2:00
|
||||
5:00 - DAVT 2012 Feb 21 20:00u
|
||||
7:00 - DAVT
|
||||
Zone Antarctica/Mawson 0 - zzz 1954 Feb 13
|
||||
Zone Antarctica/Mawson 0 - -00 1954 Feb 13
|
||||
6:00 - MAWT 2009 Oct 18 2:00 # Mawson Time
|
||||
5:00 - MAWT
|
||||
# References:
|
||||
@ -160,7 +160,7 @@ Zone Antarctica/Mawson 0 - zzz 1954 Feb 13
|
||||
# fishing stations operated variously 1819/1931
|
||||
#
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone Indian/Kerguelen 0 - zzz 1950 # Port-aux-Français
|
||||
Zone Indian/Kerguelen 0 - -00 1950 # Port-aux-Français
|
||||
5:00 - TFT # ISO code TF Time
|
||||
#
|
||||
# year-round base in the main continent
|
||||
@ -171,9 +171,9 @@ Zone Indian/Kerguelen 0 - zzz 1950 # Port-aux-Français
|
||||
# It was destroyed by fire on 1952-01-14.
|
||||
#
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone Antarctica/DumontDUrville 0 - zzz 1947
|
||||
Zone Antarctica/DumontDUrville 0 - -00 1947
|
||||
10:00 - PMT 1952 Jan 14 # Port-Martin Time
|
||||
0 - zzz 1956 Nov
|
||||
0 - -00 1956 Nov
|
||||
10:00 - DDUT # Dumont-d'Urville Time
|
||||
|
||||
# France & Italy - year-round base
|
||||
@ -199,7 +199,7 @@ Zone Antarctica/DumontDUrville 0 - zzz 1947
|
||||
# was established on 1957-01-29. Since Syowa station is still the main
|
||||
# station of Japan, it's appropriate for the principal location.
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone Antarctica/Syowa 0 - zzz 1957 Jan 29
|
||||
Zone Antarctica/Syowa 0 - -00 1957 Jan 29
|
||||
3:00 - SYOT # Syowa Time
|
||||
# See:
|
||||
# NIPR Antarctic Research Activities (1999-08-17)
|
||||
@ -249,7 +249,7 @@ Rule Troll 2005 max - Mar lastSun 1:00u 2:00 CEST
|
||||
# Remove the following line when uncommenting the above '#Rule' lines.
|
||||
Rule Troll 2004 max - Oct lastSun 1:00u 0:00 UTC
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone Antarctica/Troll 0 - zzz 2005 Feb 12
|
||||
Zone Antarctica/Troll 0 - -00 2005 Feb 12
|
||||
0:00 Troll %s
|
||||
|
||||
# Poland - year-round base
|
||||
@ -290,7 +290,7 @@ Zone Antarctica/Troll 0 - zzz 2005 Feb 12
|
||||
# happened to be during their visit. So we still don't really know what time
|
||||
# it is at Vostok. But we'll guess UTC+6.
|
||||
#
|
||||
Zone Antarctica/Vostok 0 - zzz 1957 Dec 16
|
||||
Zone Antarctica/Vostok 0 - -00 1957 Dec 16
|
||||
6:00 - VOST # Vostok time
|
||||
|
||||
# S Africa - year-round bases
|
||||
@ -323,7 +323,7 @@ Zone Antarctica/Vostok 0 - zzz 1957 Dec 16
|
||||
# <http://webexhibits.org/daylightsaving/g.html> says Rothera is -03 all year.
|
||||
#
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone Antarctica/Rothera 0 - zzz 1976 Dec 1
|
||||
Zone Antarctica/Rothera 0 - -00 1976 Dec 1
|
||||
-3:00 - ROTT # Rothera time
|
||||
|
||||
# Uruguay - year round base
|
||||
|
@ -169,7 +169,7 @@ Zone Asia/Baku 3:19:24 - LMT 1924 May 2
|
||||
3:00 - BAKT 1957 Mar # Baku Time
|
||||
4:00 RussiaAsia BAK%sT 1991 Mar 31 2:00s
|
||||
3:00 1:00 BAKST 1991 Aug 30 # independence
|
||||
3:00 RussiaAsia AZ%sT 1992 Sep lastSat 23:00
|
||||
3:00 RussiaAsia AZ%sT 1992 Sep lastSun 2:00s
|
||||
4:00 - AZT 1996 # Azerbaijan Time
|
||||
4:00 EUAsia AZ%sT 1997
|
||||
4:00 Azer AZ%sT
|
||||
|
@ -266,11 +266,11 @@ Zone Australia/Lord_Howe 10:36:20 - LMT 1895 Feb
|
||||
# will produce a binary file with an [A]EST-type as the first 32-bit type;
|
||||
# this is required for correct handling of times before 1916 by
|
||||
# pre-2013 versions of localtime.
|
||||
Zone Antarctica/Macquarie 0 - zzz 1899 Nov
|
||||
Zone Antarctica/Macquarie 0 - -00 1899 Nov
|
||||
10:00 - AEST 1916 Oct 1 2:00
|
||||
10:00 1:00 AEDT 1917 Feb
|
||||
10:00 Aus AE%sT 1919 Apr 1 0:00s
|
||||
0 - zzz 1948 Mar 25
|
||||
0 - -00 1948 Mar 25
|
||||
10:00 Aus AE%sT 1967
|
||||
10:00 AT AE%sT 2010 Apr 4 3:00
|
||||
11:00 - MIST # Macquarie I Standard Time
|
||||
|
@ -778,6 +778,14 @@ Zone Europe/Vienna 1:05:21 - LMT 1893 Apr
|
||||
1:00 EU CE%sT
|
||||
|
||||
# Belarus
|
||||
#
|
||||
# From Stepan Golosunov (2016-07-02):
|
||||
# http://www.lawbelarus.com/repub/sub30/texf9611.htm
|
||||
# (Act of the Cabinet of Ministers of the Republic of Belarus from
|
||||
# 1992-03-25 No. 157) ... says clocks were to be moved forward at 2:00
|
||||
# on last Sunday of March and backward at 3:00 on last Sunday of September
|
||||
# (the same as previous USSR and contemporary Russian regulations).
|
||||
#
|
||||
# From Yauhen Kharuzhy (2011-09-16):
|
||||
# By latest Belarus government act Europe/Minsk timezone was changed to
|
||||
# GMT+3 without DST (was GMT+2 with DST).
|
||||
@ -801,9 +809,6 @@ Zone Europe/Minsk 1:50:16 - LMT 1880
|
||||
1:00 C-Eur CE%sT 1944 Jul 3
|
||||
3:00 Russia MSK/MSD 1990
|
||||
3:00 - MSK 1991 Mar 31 2:00s
|
||||
2:00 1:00 EEST 1991 Sep 29 2:00s
|
||||
2:00 - EET 1992 Mar 29 0:00s
|
||||
2:00 1:00 EEST 1992 Sep 27 0:00s
|
||||
2:00 Russia EE%sT 2011 Mar 27 2:00s
|
||||
3:00 - FET 2014 Oct 26 1:00s
|
||||
3:00 - MSK
|
||||
@ -2746,14 +2751,22 @@ Zone Asia/Barnaul 5:35:00 - LMT 1919 Dec 10
|
||||
# Asia/Novosibirsk covers:
|
||||
# 54 RU-NVS Novosibirsk Oblast
|
||||
|
||||
# From Stepan Golosunov (2016-05-30):
|
||||
# http://asozd2.duma.gov.ru/main.nsf/(Spravka)?OpenAgent&RN=1085784-6
|
||||
# moves Novosibirsk oblast from UTC+6 to UTC+7.
|
||||
# From Stepan Golosunov (2016-07-04):
|
||||
# The law was signed yesterday and published today on
|
||||
# http://publication.pravo.gov.ru/Document/View/0001201607040064
|
||||
|
||||
Zone Asia/Novosibirsk 5:31:40 - LMT 1919 Dec 14 6:00
|
||||
6:00 - NOVT 1930 Jun 21 # Novosibirsk Time
|
||||
7:00 Russia NOV%sT 1991 Mar 31 2:00s
|
||||
6:00 Russia NOV%sT 1992 Jan 19 2:00s
|
||||
7:00 Russia NOV%sT 1993 May 23 # say Shanks & P.
|
||||
6:00 Russia NOV%sT 2011 Mar 27 2:00s
|
||||
7:00 - NOVT 2014 Oct 26 2:00s
|
||||
6:00 - NOVT
|
||||
6:00 - +06 1930 Jun 21
|
||||
7:00 Russia +07/+08 1991 Mar 31 2:00s
|
||||
6:00 Russia +06/+07 1992 Jan 19 2:00s
|
||||
7:00 Russia +07/+08 1993 May 23 # say Shanks & P.
|
||||
6:00 Russia +06/+07 2011 Mar 27 2:00s
|
||||
7:00 - +07 2014 Oct 26 2:00s
|
||||
6:00 - +06 2016 Jul 24 2:00s
|
||||
7:00 - +07
|
||||
|
||||
# From Paul Eggert (2016-03-18):
|
||||
# Asia/Tomsk covers:
|
||||
@ -2794,6 +2807,9 @@ Zone Asia/Novosibirsk 5:31:40 - LMT 1919 Dec 14 6:00
|
||||
# approved by the Federation Council on 2016-04-20, signed by the President and
|
||||
# published as a law around 2016-04-26.
|
||||
|
||||
# From Matt Johnson (2016-04-26):
|
||||
# http://publication.pravo.gov.ru/Document/View/0001201604260048
|
||||
|
||||
Zone Asia/Tomsk 5:39:51 - LMT 1919 Dec 22
|
||||
6:00 - +06 1930 Jun 21
|
||||
7:00 Russia +07/+08 1991 Mar 31 2:00s
|
||||
@ -2833,14 +2849,12 @@ Zone Asia/Tomsk 5:39:51 - LMT 1919 Dec 22
|
||||
# realigning itself with KRAT.
|
||||
|
||||
Zone Asia/Novokuznetsk 5:48:48 - LMT 1924 May 1
|
||||
6:00 - KRAT 1930 Jun 21 # Krasnoyarsk Time
|
||||
7:00 Russia KRA%sT 1991 Mar 31 2:00s
|
||||
6:00 Russia KRA%sT 1992 Jan 19 2:00s
|
||||
7:00 Russia KRA%sT 2010 Mar 28 2:00s
|
||||
6:00 Russia NOV%sT 2011 Mar 27 2:00s # Novosibirsk
|
||||
7:00 - NOVT 2014 Oct 26 2:00s
|
||||
7:00 - KRAT # Krasnoyarsk Time
|
||||
|
||||
6:00 - +06 1930 Jun 21
|
||||
7:00 Russia +07/+08 1991 Mar 31 2:00s
|
||||
6:00 Russia +06/+07 1992 Jan 19 2:00s
|
||||
7:00 Russia +07/+08 2010 Mar 28 2:00s
|
||||
6:00 Russia +06/+07 2011 Mar 27 2:00s
|
||||
7:00 - +07
|
||||
|
||||
# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
|
||||
# Asia/Krasnoyarsk covers...
|
||||
|
@ -2214,39 +2214,39 @@ Rule NT_YK 1980 2006 - Oct lastSun 2:00 0 S
|
||||
Rule NT_YK 1987 2006 - Apr Sun>=1 2:00 1:00 D
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
# aka Panniqtuuq
|
||||
Zone America/Pangnirtung 0 - zzz 1921 # trading post est.
|
||||
Zone America/Pangnirtung 0 - -00 1921 # trading post est.
|
||||
-4:00 NT_YK A%sT 1995 Apr Sun>=1 2:00
|
||||
-5:00 Canada E%sT 1999 Oct 31 2:00
|
||||
-6:00 Canada C%sT 2000 Oct 29 2:00
|
||||
-5:00 Canada E%sT
|
||||
# formerly Frobisher Bay
|
||||
Zone America/Iqaluit 0 - zzz 1942 Aug # Frobisher Bay est.
|
||||
Zone America/Iqaluit 0 - -00 1942 Aug # Frobisher Bay est.
|
||||
-5:00 NT_YK E%sT 1999 Oct 31 2:00
|
||||
-6:00 Canada C%sT 2000 Oct 29 2:00
|
||||
-5:00 Canada E%sT
|
||||
# aka Qausuittuq
|
||||
Zone America/Resolute 0 - zzz 1947 Aug 31 # Resolute founded
|
||||
Zone America/Resolute 0 - -00 1947 Aug 31 # Resolute founded
|
||||
-6:00 NT_YK C%sT 2000 Oct 29 2:00
|
||||
-5:00 - EST 2001 Apr 1 3:00
|
||||
-6:00 Canada C%sT 2006 Oct 29 2:00
|
||||
-5:00 - EST 2007 Mar 11 3:00
|
||||
-6:00 Canada C%sT
|
||||
# aka Kangiqiniq
|
||||
Zone America/Rankin_Inlet 0 - zzz 1957 # Rankin Inlet founded
|
||||
Zone America/Rankin_Inlet 0 - -00 1957 # Rankin Inlet founded
|
||||
-6:00 NT_YK C%sT 2000 Oct 29 2:00
|
||||
-5:00 - EST 2001 Apr 1 3:00
|
||||
-6:00 Canada C%sT
|
||||
# aka Iqaluktuuttiaq
|
||||
Zone America/Cambridge_Bay 0 - zzz 1920 # trading post est.?
|
||||
Zone America/Cambridge_Bay 0 - -00 1920 # trading post est.?
|
||||
-7:00 NT_YK M%sT 1999 Oct 31 2:00
|
||||
-6:00 Canada C%sT 2000 Oct 29 2:00
|
||||
-5:00 - EST 2000 Nov 5 0:00
|
||||
-6:00 - CST 2001 Apr 1 3:00
|
||||
-7:00 Canada M%sT
|
||||
Zone America/Yellowknife 0 - zzz 1935 # Yellowknife founded?
|
||||
Zone America/Yellowknife 0 - -00 1935 # Yellowknife founded?
|
||||
-7:00 NT_YK M%sT 1980
|
||||
-7:00 Canada M%sT
|
||||
Zone America/Inuvik 0 - zzz 1953 # Inuvik founded
|
||||
Zone America/Inuvik 0 - -00 1953 # Inuvik founded
|
||||
-8:00 NT_YK P%sT 1979 Apr lastSun 2:00
|
||||
-7:00 NT_YK M%sT 1980
|
||||
-7:00 Canada M%sT
|
||||
|
@ -1332,7 +1332,7 @@ Zone Pacific/Easter -7:17:28 - LMT 1890
|
||||
# Palmer used to be supplied from Argentina.
|
||||
#
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone Antarctica/Palmer 0 - zzz 1965
|
||||
Zone Antarctica/Palmer 0 - -00 1965
|
||||
-4:00 Arg AR%sT 1969 Oct 5
|
||||
-3:00 Arg AR%sT 1982 May
|
||||
-4:00 Chile CL%sT
|
||||
@ -1782,16 +1782,16 @@ Zone America/Montevideo -3:44:44 - LMT 1898 Jun 28
|
||||
# https://actualidad.rt.com/actualidad/204758-venezuela-modificar-huso-horario-sequia-elnino
|
||||
#
|
||||
# From Paul Eggert (2016-04-15):
|
||||
# Clocks advance 30 minutes on 2016-05-01 at 02:30. See:
|
||||
# Barboza AD. Huso horario en Venezuela volverá a 4 horas menos con
|
||||
# respecto al "Greenwich". Panorama 2016-04-15 12:20 -0430.
|
||||
# http://www.panorama.com.ve/ciudad/Huso-horario-en-Venezuela-volvera-a-4-horas-menos-con-respecto-al-Greenwich-20160415-0032.html
|
||||
#
|
||||
# Clocks advance 30 minutes on 2016-05-01 at 02:30....
|
||||
# "'Venezuela's new time-zone: hours without light, hours without water,
|
||||
# hours of presidential broadcasts, hours of lines," quipped comedian
|
||||
# Jean Mary Curro ...". See: Cawthorne A, Kai D. Venezuela scraps
|
||||
# hours of presidential broadcasts, hours of lines,' quipped comedian
|
||||
# Jean Mary Curró ...". See: Cawthorne A, Kai D. Venezuela scraps
|
||||
# half-hour time difference set by Chavez. Reuters 2016-04-15 14:50 -0400
|
||||
# http://www.reuters.com/article/us-venezuela-timezone-idUSKCN0XC2BE
|
||||
#
|
||||
# From Matt Johnson (2016-04-20):
|
||||
# ... published in the official Gazette [2016-04-18], here:
|
||||
# http://historico.tsj.gob.ve/gaceta_ext/abril/1842016/E-1842016-4551.pdf
|
||||
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone America/Caracas -4:27:44 - LMT 1890
|
||||
|
@ -917,7 +917,7 @@ ifndef BUILD_HEADLESS_ONLY
|
||||
LIBSPLASHSCREEN_LDFLAGS := -delayload:user32.dll
|
||||
LIBSPLASHSCREEN_LIBS += kernel32.lib user32.lib gdi32.lib delayimp.lib $(WIN_JAVA_LIB) jvm.lib
|
||||
else
|
||||
LIBSPLASHSCREEN_LIBS += $(X_LIBS) -lX11 -lXext $(LIBM) -lpthread
|
||||
LIBSPLASHSCREEN_LIBS += $(X_LIBS) -lX11 -lXext $(LIBM) -lpthread -ldl
|
||||
endif
|
||||
|
||||
$(eval $(call SetupNativeCompilation,BUILD_LIBSPLASHSCREEN, \
|
||||
|
@ -164,6 +164,7 @@ SUNWprivate_1.1 {
|
||||
Java_sun_awt_X11_XRobotPeer_mouseReleaseImpl;
|
||||
Java_sun_awt_X11_XRobotPeer_mouseWheelImpl;
|
||||
Java_sun_awt_X11_XRobotPeer_setup;
|
||||
Java_sun_awt_X11_XRobotPeer_loadNativeLibraries;
|
||||
Java_sun_awt_X11_XToolkit_getNumberOfButtonsImpl;
|
||||
Java_java_awt_Component_initIDs;
|
||||
Java_java_awt_Container_initIDs;
|
||||
|
@ -136,10 +136,6 @@ SUNWprivate_1.1 {
|
||||
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
|
||||
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
|
||||
Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
|
||||
Java_sun_nio_fs_GioFileTypeDetector_initializeGio;
|
||||
Java_sun_nio_fs_GioFileTypeDetector_probeGio;
|
||||
Java_sun_nio_fs_MagicFileTypeDetector_initialize0;
|
||||
Java_sun_nio_fs_MagicFileTypeDetector_probe0;
|
||||
Java_sun_nio_fs_LinuxWatchService_eventSize;
|
||||
Java_sun_nio_fs_LinuxWatchService_eventOffsets;
|
||||
Java_sun_nio_fs_LinuxWatchService_inotifyInit;
|
||||
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 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 sun.nio.fs;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.io.IOException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* File type detector that uses the GNOME I/O library to guess the
|
||||
* MIME type of a file.
|
||||
*/
|
||||
|
||||
public class GioFileTypeDetector
|
||||
extends AbstractFileTypeDetector
|
||||
{
|
||||
// true if GIO is available
|
||||
private final boolean gioAvailable;
|
||||
|
||||
public GioFileTypeDetector() {
|
||||
gioAvailable = initializeGio();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String implProbeContentType(Path obj) throws IOException {
|
||||
if (!gioAvailable)
|
||||
return null;
|
||||
if (!(obj instanceof UnixPath))
|
||||
return null;
|
||||
|
||||
UnixPath path = (UnixPath)obj;
|
||||
NativeBuffer buffer = NativeBuffers.asNativeBuffer(path.getByteArrayForSysCalls());
|
||||
try {
|
||||
// GIO may access file so need permission check
|
||||
path.checkRead();
|
||||
byte[] type = probeGio(buffer.address());
|
||||
return (type == null) ? null : Util.toString(type);
|
||||
} finally {
|
||||
buffer.release();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// GIO
|
||||
private static native boolean initializeGio();
|
||||
//
|
||||
// The probeGIO() method is synchronized to avert potential problems
|
||||
// such as crashes due to a suspected lack of thread safety in GIO.
|
||||
//
|
||||
private static synchronized native byte[] probeGio(long pathAddress);
|
||||
|
||||
static {
|
||||
AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
public Void run() {
|
||||
System.loadLibrary("nio");
|
||||
return null;
|
||||
}});
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2016, 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
|
||||
@ -106,9 +106,7 @@ public class LinuxFileSystemProvider extends UnixFileSystemProvider {
|
||||
Path userMimeTypes = Paths.get(userHome, ".mime.types");
|
||||
Path etcMimeTypes = Paths.get("/etc/mime.types");
|
||||
|
||||
return chain(new GioFileTypeDetector(),
|
||||
new MimeTypesFileTypeDetector(userMimeTypes),
|
||||
new MimeTypesFileTypeDetector(etcMimeTypes),
|
||||
new MagicFileTypeDetector());
|
||||
return chain(new MimeTypesFileTypeDetector(userMimeTypes),
|
||||
new MimeTypesFileTypeDetector(etcMimeTypes));
|
||||
}
|
||||
}
|
||||
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 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 sun.nio.fs;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* File type detector that uses the libmagic to guess the MIME type of a file.
|
||||
*/
|
||||
|
||||
class MagicFileTypeDetector extends AbstractFileTypeDetector {
|
||||
|
||||
private static final String UNKNOWN_MIME_TYPE = "application/octet-stream";
|
||||
|
||||
// true if libmagic is available and successfully loaded
|
||||
private final boolean libmagicAvailable;
|
||||
|
||||
public MagicFileTypeDetector() {
|
||||
libmagicAvailable = initialize0();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String implProbeContentType(Path obj) throws IOException {
|
||||
if (!libmagicAvailable || !(obj instanceof UnixPath))
|
||||
return null;
|
||||
|
||||
UnixPath path = (UnixPath) obj;
|
||||
path.checkRead();
|
||||
|
||||
NativeBuffer buffer = NativeBuffers.asNativeBuffer(path.getByteArrayForSysCalls());
|
||||
try {
|
||||
byte[] type = probe0(buffer.address());
|
||||
String mimeType = (type == null) ? null : new String(type);
|
||||
return UNKNOWN_MIME_TYPE.equals(mimeType) ? null : mimeType;
|
||||
} finally {
|
||||
buffer.release();
|
||||
}
|
||||
}
|
||||
|
||||
private static native boolean initialize0();
|
||||
|
||||
private static native byte[] probe0(long pathAddress);
|
||||
|
||||
static {
|
||||
AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
System.loadLibrary("nio");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2016, 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.
|
||||
*/
|
||||
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "jvm.h"
|
||||
#include "jlong.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#ifdef __solaris__
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For reference see for example the GFileInfo section at
|
||||
* https://developer.gnome.org/gio/unstable/.
|
||||
*/
|
||||
|
||||
/* Definitions for GIO */
|
||||
|
||||
#define G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "standard::content-type"
|
||||
|
||||
typedef void* gpointer;
|
||||
typedef struct _GFile GFile;
|
||||
typedef struct _GFileInfo GFileInfo;
|
||||
typedef struct _GCancellable GCancellable;
|
||||
typedef struct _GError GError;
|
||||
|
||||
typedef enum {
|
||||
G_FILE_QUERY_INFO_NONE = 0
|
||||
} GFileQueryInfoFlags;
|
||||
|
||||
typedef void (*g_type_init_func)(void);
|
||||
typedef void (*g_object_unref_func)(gpointer object);
|
||||
typedef GFile* (*g_file_new_for_path_func)(const char* path);
|
||||
typedef GFileInfo* (*g_file_query_info_func)(GFile *file,
|
||||
const char *attributes, GFileQueryInfoFlags flags,
|
||||
GCancellable *cancellable, GError **error);
|
||||
typedef char* (*g_file_info_get_content_type_func)(GFileInfo *info);
|
||||
|
||||
static g_type_init_func g_type_init;
|
||||
static g_object_unref_func g_object_unref;
|
||||
static g_file_new_for_path_func g_file_new_for_path;
|
||||
static g_file_query_info_func g_file_query_info;
|
||||
static g_file_info_get_content_type_func g_file_info_get_content_type;
|
||||
|
||||
|
||||
#include "sun_nio_fs_GioFileTypeDetector.h"
|
||||
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_fs_GioFileTypeDetector_initializeGio
|
||||
(JNIEnv* env, jclass this)
|
||||
{
|
||||
void* gio_handle;
|
||||
|
||||
gio_handle = dlopen("libgio-2.0.so", RTLD_LAZY);
|
||||
if (gio_handle == NULL) {
|
||||
gio_handle = dlopen("libgio-2.0.so.0", RTLD_LAZY);
|
||||
if (gio_handle == NULL) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
g_type_init = (g_type_init_func)dlsym(gio_handle, "g_type_init");
|
||||
|
||||
g_object_unref = (g_object_unref_func)dlsym(gio_handle, "g_object_unref");
|
||||
|
||||
g_file_new_for_path =
|
||||
(g_file_new_for_path_func)dlsym(gio_handle, "g_file_new_for_path");
|
||||
|
||||
g_file_query_info =
|
||||
(g_file_query_info_func)dlsym(gio_handle, "g_file_query_info");
|
||||
|
||||
g_file_info_get_content_type = (g_file_info_get_content_type_func)
|
||||
dlsym(gio_handle, "g_file_info_get_content_type");
|
||||
|
||||
if (g_object_unref == NULL ||
|
||||
g_file_new_for_path == NULL ||
|
||||
g_file_query_info == NULL ||
|
||||
g_file_info_get_content_type == NULL)
|
||||
{
|
||||
dlclose(gio_handle);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
if (g_type_init != NULL) {
|
||||
(*g_type_init)();
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_sun_nio_fs_GioFileTypeDetector_probeGio
|
||||
(JNIEnv* env, jclass this, jlong pathAddress)
|
||||
{
|
||||
char* path = (char*)jlong_to_ptr(pathAddress);
|
||||
GFile* gfile;
|
||||
GFileInfo* gfileinfo;
|
||||
jbyteArray result = NULL;
|
||||
|
||||
gfile = (*g_file_new_for_path)(path);
|
||||
gfileinfo = (*g_file_query_info)(gfile, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
|
||||
G_FILE_QUERY_INFO_NONE, NULL, NULL);
|
||||
if (gfileinfo != NULL) {
|
||||
const char* mime = (*g_file_info_get_content_type)(gfileinfo);
|
||||
if (mime != NULL) {
|
||||
jsize len = strlen(mime);
|
||||
result = (*env)->NewByteArray(env, len);
|
||||
if (result != NULL) {
|
||||
(*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)mime);
|
||||
}
|
||||
}
|
||||
(*g_object_unref)(gfileinfo);
|
||||
}
|
||||
(*g_object_unref)(gfile);
|
||||
|
||||
return result;
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 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.
|
||||
*/
|
||||
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "jvm.h"
|
||||
#include "jlong.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAGIC_MIME_TYPE 0x000010 /* Return the MIME type */
|
||||
|
||||
typedef struct magic_set magic_t;
|
||||
|
||||
typedef magic_t* (*magic_open_func)(int flags);
|
||||
typedef int (*magic_load_func)(magic_t* cookie, const char* filename);
|
||||
typedef const char* (*magic_file_func)(magic_t* cookie, const char* filename);
|
||||
typedef void (*magic_close_func)(magic_t* cookie);
|
||||
|
||||
static void* magic_handle;
|
||||
static magic_open_func magic_open;
|
||||
static magic_load_func magic_load;
|
||||
static magic_file_func magic_file;
|
||||
static magic_close_func magic_close;
|
||||
|
||||
#include "sun_nio_fs_MagicFileTypeDetector.h"
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_fs_MagicFileTypeDetector_initialize0
|
||||
(JNIEnv* env, jclass this)
|
||||
{
|
||||
magic_handle = dlopen("libmagic.so", RTLD_LAZY);
|
||||
if (magic_handle == NULL) {
|
||||
magic_handle = dlopen("libmagic.so.1", RTLD_LAZY);
|
||||
if (magic_handle == NULL) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
magic_open = (magic_open_func)dlsym(magic_handle, "magic_open");
|
||||
|
||||
magic_load = (magic_load_func)dlsym(magic_handle, "magic_load");
|
||||
|
||||
magic_file = (magic_file_func)dlsym(magic_handle, "magic_file");
|
||||
|
||||
magic_close = (magic_close_func)dlsym(magic_handle, "magic_close");
|
||||
|
||||
if (magic_open == NULL ||
|
||||
magic_load == NULL ||
|
||||
magic_file == NULL ||
|
||||
magic_close == NULL)
|
||||
{
|
||||
dlclose(magic_handle);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_sun_nio_fs_MagicFileTypeDetector_probe0
|
||||
(JNIEnv* env, jclass this, jlong pathAddress)
|
||||
{
|
||||
char* path = (char*)jlong_to_ptr(pathAddress);
|
||||
magic_t* cookie;
|
||||
jbyteArray result = NULL;
|
||||
|
||||
cookie = (*magic_open)(MAGIC_MIME_TYPE);
|
||||
|
||||
if (cookie != NULL) {
|
||||
if ((*magic_load)(cookie, NULL) != -1) {
|
||||
const char* type = (*magic_file)(cookie, path);
|
||||
if (type != NULL) {
|
||||
jsize len = strlen(type);
|
||||
result = (*env)->NewByteArray(env, len);
|
||||
if (result != NULL) {
|
||||
(*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*)type);
|
||||
}
|
||||
}
|
||||
}
|
||||
(*magic_close)(cookie);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -236,10 +236,12 @@ public final class System {
|
||||
* @since 1.6
|
||||
*/
|
||||
public static Console console() {
|
||||
Console c = cons;
|
||||
if (c == null) {
|
||||
Console c;
|
||||
if ((c = cons) == null) {
|
||||
synchronized (System.class) {
|
||||
cons = c = SharedSecrets.getJavaIOAccess().console();
|
||||
if ((c = cons) == null) {
|
||||
cons = c = SharedSecrets.getJavaIOAccess().console();
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
|
@ -122,7 +122,7 @@ public abstract class Executable extends AccessibleObject
|
||||
sb.append(')');
|
||||
|
||||
if (exceptionTypes.length > 0) {
|
||||
StringJoiner joiner = new StringJoiner(",", "throws ", "");
|
||||
StringJoiner joiner = new StringJoiner(",", " throws ", "");
|
||||
for (Class<?> exceptionType : exceptionTypes) {
|
||||
joiner.add(exceptionType.getTypeName());
|
||||
}
|
||||
|
@ -338,6 +338,7 @@ public final class LocalDate
|
||||
* @throws DateTimeException if the epoch day exceeds the supported date range
|
||||
*/
|
||||
public static LocalDate ofEpochDay(long epochDay) {
|
||||
EPOCH_DAY.checkValidValue(epochDay);
|
||||
long zeroDay = epochDay + DAYS_0000_TO_1970;
|
||||
// find the march-based year
|
||||
zeroDay -= 60; // adjust to 0000-03-01 so leap day is at end of four year cycle
|
||||
|
@ -928,7 +928,24 @@ public final class DateTimeFormatterBuilder {
|
||||
* second if non-zero, no colon
|
||||
* <li>{@code +HH:mm:ss} - hour, with minute if non-zero or with minute and
|
||||
* second if non-zero, with colon
|
||||
* <li>{@code +H} - hour only, ignoring minute and second
|
||||
* <li>{@code +Hmm} - hour, with minute if non-zero, ignoring second, no colon
|
||||
* <li>{@code +H:mm} - hour, with minute if non-zero, ignoring second, with colon
|
||||
* <li>{@code +HMM} - hour and minute, ignoring second, no colon
|
||||
* <li>{@code +H:MM} - hour and minute, ignoring second, with colon
|
||||
* <li>{@code +HMMss} - hour and minute, with second if non-zero, no colon
|
||||
* <li>{@code +H:MM:ss} - hour and minute, with second if non-zero, with colon
|
||||
* <li>{@code +HMMSS} - hour, minute and second, no colon
|
||||
* <li>{@code +H:MM:SS} - hour, minute and second, with colon
|
||||
* <li>{@code +Hmmss} - hour, with minute if non-zero or with minute and
|
||||
* second if non-zero, no colon
|
||||
* <li>{@code +H:mm:ss} - hour, with minute if non-zero or with minute and
|
||||
* second if non-zero, with colon
|
||||
* </ul>
|
||||
* Patterns containing "HH" will format and parse a two digit hour,
|
||||
* zero-padded if necessary. Patterns containing "H" will format with no
|
||||
* zero-padding, and parse either one or two digits.
|
||||
* In lenient mode, the parser will be greedy and parse the maximum digits possible.
|
||||
* The "no offset" text controls what text is printed when the total amount of
|
||||
* the offset fields to be output is zero.
|
||||
* Example values would be 'Z', '+00:00', 'UTC' or 'GMT'.
|
||||
@ -3475,13 +3492,15 @@ public final class DateTimeFormatterBuilder {
|
||||
*/
|
||||
static final class OffsetIdPrinterParser implements DateTimePrinterParser {
|
||||
static final String[] PATTERNS = new String[] {
|
||||
"+HH", "+HHmm", "+HH:mm", "+HHMM", "+HH:MM", "+HHMMss", "+HH:MM:ss", "+HHMMSS", "+HH:MM:SS", "+HHmmss", "+HH:mm:ss",
|
||||
"+HH", "+HHmm", "+HH:mm", "+HHMM", "+HH:MM", "+HHMMss", "+HH:MM:ss", "+HHMMSS", "+HH:MM:SS", "+HHmmss", "+HH:mm:ss",
|
||||
"+H", "+Hmm", "+H:mm", "+HMM", "+H:MM", "+HMMss", "+H:MM:ss", "+HMMSS", "+H:MM:SS", "+Hmmss", "+H:mm:ss",
|
||||
}; // order used in pattern builder
|
||||
static final OffsetIdPrinterParser INSTANCE_ID_Z = new OffsetIdPrinterParser("+HH:MM:ss", "Z");
|
||||
static final OffsetIdPrinterParser INSTANCE_ID_ZERO = new OffsetIdPrinterParser("+HH:MM:ss", "0");
|
||||
|
||||
private final String noOffsetText;
|
||||
private final int type;
|
||||
private final int style;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -3493,6 +3512,7 @@ public final class DateTimeFormatterBuilder {
|
||||
Objects.requireNonNull(pattern, "pattern");
|
||||
Objects.requireNonNull(noOffsetText, "noOffsetText");
|
||||
this.type = checkPattern(pattern);
|
||||
this.style = type % 11;
|
||||
this.noOffsetText = noOffsetText;
|
||||
}
|
||||
|
||||
@ -3505,6 +3525,14 @@ public final class DateTimeFormatterBuilder {
|
||||
throw new IllegalArgumentException("Invalid zone offset pattern: " + pattern);
|
||||
}
|
||||
|
||||
private boolean isPaddedHour() {
|
||||
return type < 11;
|
||||
}
|
||||
|
||||
private boolean isColon() {
|
||||
return style > 0 && (style % 2) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean format(DateTimePrintContext context, StringBuilder buf) {
|
||||
Long offsetSecs = context.getValue(OFFSET_SECONDS);
|
||||
@ -3520,15 +3548,17 @@ public final class DateTimeFormatterBuilder {
|
||||
int absSeconds = Math.abs(totalSecs % 60);
|
||||
int bufPos = buf.length();
|
||||
int output = absHours;
|
||||
buf.append(totalSecs < 0 ? "-" : "+")
|
||||
.append((char) (absHours / 10 + '0')).append((char) (absHours % 10 + '0'));
|
||||
if ((type >= 3 && type < 9) || (type >= 9 && absSeconds > 0) || (type >= 1 && absMinutes > 0)) {
|
||||
buf.append((type % 2) == 0 ? ":" : "")
|
||||
.append((char) (absMinutes / 10 + '0')).append((char) (absMinutes % 10 + '0'));
|
||||
buf.append(totalSecs < 0 ? "-" : "+");
|
||||
if (isPaddedHour() || absHours >= 10) {
|
||||
formatZeroPad(false, absHours, buf);
|
||||
} else {
|
||||
buf.append((char) (absHours + '0'));
|
||||
}
|
||||
if ((style >= 3 && style <= 8) || (style >= 9 && absSeconds > 0) || (style >= 1 && absMinutes > 0)) {
|
||||
formatZeroPad(isColon(), absMinutes, buf);
|
||||
output += absMinutes;
|
||||
if (type == 7 || type == 8 || (type >= 5 && absSeconds > 0)) {
|
||||
buf.append((type % 2) == 0 ? ":" : "")
|
||||
.append((char) (absSeconds / 10 + '0')).append((char) (absSeconds % 10 + '0'));
|
||||
if (style == 7 || style == 8 || (style >= 5 && absSeconds > 0)) {
|
||||
formatZeroPad(isColon(), absSeconds, buf);
|
||||
output += absSeconds;
|
||||
}
|
||||
}
|
||||
@ -3540,19 +3570,16 @@ public final class DateTimeFormatterBuilder {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void formatZeroPad(boolean colon, int value, StringBuilder buf) {
|
||||
buf.append(colon ? ":" : "")
|
||||
.append((char) (value / 10 + '0'))
|
||||
.append((char) (value % 10 + '0'));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int parse(DateTimeParseContext context, CharSequence text, int position) {
|
||||
int length = text.length();
|
||||
int noOffsetLen = noOffsetText.length();
|
||||
int parseType = type;
|
||||
if (context.isStrict() == false) {
|
||||
if ((parseType > 0 && (parseType % 2) == 0) ||
|
||||
(parseType == 0 && length > position + 3 && text.charAt(position + 3) == ':')) {
|
||||
parseType = 10;
|
||||
} else {
|
||||
parseType = 9;
|
||||
}
|
||||
}
|
||||
if (noOffsetLen == 0) {
|
||||
if (position == length) {
|
||||
return context.setParsedField(OFFSET_SECONDS, 0, position, position);
|
||||
@ -3571,12 +3598,87 @@ public final class DateTimeFormatterBuilder {
|
||||
if (sign == '+' || sign == '-') {
|
||||
// starts
|
||||
int negative = (sign == '-' ? -1 : 1);
|
||||
boolean isColon = isColon();
|
||||
boolean paddedHour = isPaddedHour();
|
||||
int[] array = new int[4];
|
||||
array[0] = position + 1;
|
||||
if ((parseNumber(array, 1, text, true, parseType) ||
|
||||
parseNumber(array, 2, text, parseType >= 3 && parseType < 9, parseType) ||
|
||||
parseNumber(array, 3, text, parseType == 7 || parseType == 8, parseType)) == false) {
|
||||
// success
|
||||
int parseType = type;
|
||||
// select parse type when lenient
|
||||
if (!context.isStrict()) {
|
||||
if (paddedHour) {
|
||||
if (isColon || (parseType == 0 && length > position + 3 && text.charAt(position + 3) == ':')) {
|
||||
isColon = true; // needed in cases like ("+HH", "+01:01")
|
||||
parseType = 10;
|
||||
} else {
|
||||
parseType = 9;
|
||||
}
|
||||
} else {
|
||||
if (isColon || (parseType == 11 && length > position + 3 && (text.charAt(position + 2) == ':' || text.charAt(position + 3) == ':'))) {
|
||||
isColon = true;
|
||||
parseType = 21; // needed in cases like ("+H", "+1:01")
|
||||
} else {
|
||||
parseType = 20;
|
||||
}
|
||||
}
|
||||
}
|
||||
// parse according to the selected pattern
|
||||
switch (parseType) {
|
||||
case 0: // +HH
|
||||
case 11: // +H
|
||||
parseHour(text, paddedHour, array);
|
||||
break;
|
||||
case 1: // +HHmm
|
||||
case 2: // +HH:mm
|
||||
case 13: // +H:mm
|
||||
parseHour(text, paddedHour, array);
|
||||
parseMinute(text, isColon, false, array);
|
||||
break;
|
||||
case 3: // +HHMM
|
||||
case 4: // +HH:MM
|
||||
case 15: // +H:MM
|
||||
parseHour(text, paddedHour, array);
|
||||
parseMinute(text, isColon, true, array);
|
||||
break;
|
||||
case 5: // +HHMMss
|
||||
case 6: // +HH:MM:ss
|
||||
case 17: // +H:MM:ss
|
||||
parseHour(text, paddedHour, array);
|
||||
parseMinute(text, isColon, true, array);
|
||||
parseSecond(text, isColon, false, array);
|
||||
break;
|
||||
case 7: // +HHMMSS
|
||||
case 8: // +HH:MM:SS
|
||||
case 19: // +H:MM:SS
|
||||
parseHour(text, paddedHour, array);
|
||||
parseMinute(text, isColon, true, array);
|
||||
parseSecond(text, isColon, true, array);
|
||||
break;
|
||||
case 9: // +HHmmss
|
||||
case 10: // +HH:mm:ss
|
||||
case 21: // +H:mm:ss
|
||||
parseHour(text, paddedHour, array);
|
||||
parseOptionalMinuteSecond(text, isColon, array);
|
||||
break;
|
||||
case 12: // +Hmm
|
||||
parseVariableWidthDigits(text, 1, 4, array);
|
||||
break;
|
||||
case 14: // +HMM
|
||||
parseVariableWidthDigits(text, 3, 4, array);
|
||||
break;
|
||||
case 16: // +HMMss
|
||||
parseVariableWidthDigits(text, 3, 6, array);
|
||||
break;
|
||||
case 18: // +HMMSS
|
||||
parseVariableWidthDigits(text, 5, 6, array);
|
||||
break;
|
||||
case 20: // +Hmmss
|
||||
parseVariableWidthDigits(text, 1, 6, array);
|
||||
break;
|
||||
}
|
||||
if (array[0] > 0) {
|
||||
if (array[1] > 23 || array[2] > 59 || array[3] > 59) {
|
||||
throw new DateTimeException("Value out of range: Hour[0-23], Minute[0-59], Second[0-59]");
|
||||
}
|
||||
long offsetSecs = negative * (array[1] * 3600L + array[2] * 60L + array[3]);
|
||||
return context.setParsedField(OFFSET_SECONDS, offsetSecs, position, array[0]);
|
||||
}
|
||||
@ -3588,42 +3690,118 @@ public final class DateTimeFormatterBuilder {
|
||||
return ~position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a two digit zero-prefixed number.
|
||||
*
|
||||
* @param array the array of parsed data, 0=pos,1=hours,2=mins,3=secs, not null
|
||||
* @param arrayIndex the index to parse the value into
|
||||
* @param parseText the offset ID, not null
|
||||
* @param required whether this number is required
|
||||
* @param parseType the offset pattern type
|
||||
* @return true if an error occurred
|
||||
*/
|
||||
private boolean parseNumber(int[] array, int arrayIndex, CharSequence parseText, boolean required, int parseType) {
|
||||
if ((parseType + 3) / 2 < arrayIndex) {
|
||||
return false; // ignore seconds/minutes
|
||||
private void parseHour(CharSequence parseText, boolean paddedHour, int[] array) {
|
||||
if (paddedHour) {
|
||||
// parse two digits
|
||||
if (!parseDigits(parseText, false, 1, array)) {
|
||||
array[0] = ~array[0];
|
||||
}
|
||||
} else {
|
||||
// parse one or two digits
|
||||
parseVariableWidthDigits(parseText, 1, 2, array);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseMinute(CharSequence parseText, boolean isColon, boolean mandatory, int[] array) {
|
||||
if (!parseDigits(parseText, isColon, 2, array)) {
|
||||
if (mandatory) {
|
||||
array[0] = ~array[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseSecond(CharSequence parseText, boolean isColon, boolean mandatory, int[] array) {
|
||||
if (!parseDigits(parseText, isColon, 3, array)) {
|
||||
if (mandatory) {
|
||||
array[0] = ~array[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseOptionalMinuteSecond(CharSequence parseText, boolean isColon, int[] array) {
|
||||
if (parseDigits(parseText, isColon, 2, array)) {
|
||||
parseDigits(parseText, isColon, 3, array);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean parseDigits(CharSequence parseText, boolean isColon, int arrayIndex, int[] array) {
|
||||
int pos = array[0];
|
||||
if ((parseType % 2) == 0 && arrayIndex > 1) {
|
||||
if (pos < 0) {
|
||||
return true;
|
||||
}
|
||||
if (isColon && arrayIndex != 1) { // ':' will precede only in case of minute/second
|
||||
if (pos + 1 > parseText.length() || parseText.charAt(pos) != ':') {
|
||||
return required;
|
||||
return false;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
if (pos + 2 > parseText.length()) {
|
||||
return required;
|
||||
return false;
|
||||
}
|
||||
char ch1 = parseText.charAt(pos++);
|
||||
char ch2 = parseText.charAt(pos++);
|
||||
if (ch1 < '0' || ch1 > '9' || ch2 < '0' || ch2 > '9') {
|
||||
return required;
|
||||
return false;
|
||||
}
|
||||
int value = (ch1 - 48) * 10 + (ch2 - 48);
|
||||
if (value < 0 || value > 59) {
|
||||
return required;
|
||||
return false;
|
||||
}
|
||||
array[arrayIndex] = value;
|
||||
array[0] = pos;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void parseVariableWidthDigits(CharSequence parseText, int minDigits, int maxDigits, int[] array) {
|
||||
// scan the text to find the available number of digits up to maxDigits
|
||||
// so long as the number available is minDigits or more, the input is valid
|
||||
// then parse the number of available digits
|
||||
int pos = array[0];
|
||||
int available = 0;
|
||||
char[] chars = new char[maxDigits];
|
||||
for (int i = 0; i < maxDigits; i++) {
|
||||
if (pos + 1 > parseText.length()) {
|
||||
break;
|
||||
}
|
||||
char ch = parseText.charAt(pos++);
|
||||
if (ch < '0' || ch > '9') {
|
||||
pos--;
|
||||
break;
|
||||
}
|
||||
chars[i] = ch;
|
||||
available++;
|
||||
}
|
||||
if (available < minDigits) {
|
||||
array[0] = ~array[0];
|
||||
return;
|
||||
}
|
||||
switch (available) {
|
||||
case 1:
|
||||
array[1] = (chars[0] - 48);
|
||||
break;
|
||||
case 2:
|
||||
array[1] = ((chars[0] - 48) * 10 + (chars[1] - 48));
|
||||
break;
|
||||
case 3:
|
||||
array[1] = (chars[0] - 48);
|
||||
array[2] = ((chars[1] - 48) * 10 + (chars[2] - 48));
|
||||
break;
|
||||
case 4:
|
||||
array[1] = ((chars[0] - 48) * 10 + (chars[1] - 48));
|
||||
array[2] = ((chars[2] - 48) * 10 + (chars[3] - 48));
|
||||
break;
|
||||
case 5:
|
||||
array[1] = (chars[0] - 48);
|
||||
array[2] = ((chars[1] - 48) * 10 + (chars[2] - 48));
|
||||
array[3] = ((chars[3] - 48) * 10 + (chars[4] - 48));
|
||||
break;
|
||||
case 6:
|
||||
array[1] = ((chars[0] - 48) * 10 + (chars[1] - 48));
|
||||
array[2] = ((chars[2] - 48) * 10 + (chars[3] - 48));
|
||||
array[3] = ((chars[4] - 48) * 10 + (chars[5] - 48));
|
||||
break;
|
||||
}
|
||||
array[0] = pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -427,8 +427,11 @@ public enum ChronoField implements TemporalField {
|
||||
* <p>
|
||||
* This field is strictly defined to have the same meaning in all calendar systems.
|
||||
* This is necessary to ensure interoperation between calendars.
|
||||
* <p>
|
||||
* Range of EpochDay is between (LocalDate.MIN.toEpochDay(), LocalDate.MAX.toEpochDay())
|
||||
* both inclusive.
|
||||
*/
|
||||
EPOCH_DAY("EpochDay", DAYS, FOREVER, ValueRange.of((long) (Year.MIN_VALUE * 365.25), (long) (Year.MAX_VALUE * 365.25))),
|
||||
EPOCH_DAY("EpochDay", DAYS, FOREVER, ValueRange.of(-365243219162L, 365241780471L)),
|
||||
/**
|
||||
* The aligned week within a month.
|
||||
* <p>
|
||||
|
@ -153,10 +153,11 @@ public class HandshakeCompletedEvent extends EventObject
|
||||
* @exception SSLPeerUnverifiedException if the peer is not verified.
|
||||
* @see #getPeerPrincipal()
|
||||
* @deprecated The {@link #getPeerCertificates()} method that returns an
|
||||
* array of {@code java.security.cert.Certificate} should
|
||||
* be used instead.
|
||||
* array of {@code java.security.cert.Certificate} should
|
||||
* be used instead. This method is subject to removal in
|
||||
* a future version of Java SE.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated(since="9", forRemoval=true)
|
||||
public javax.security.cert.X509Certificate [] getPeerCertificateChain()
|
||||
throws SSLPeerUnverifiedException
|
||||
{
|
||||
|
@ -273,10 +273,11 @@ public interface SSLSession {
|
||||
* has not been verified
|
||||
* @see #getPeerPrincipal()
|
||||
* @deprecated The {@link #getPeerCertificates()} method that returns an
|
||||
* array of {@code java.security.cert.Certificate} should
|
||||
* be used instead.
|
||||
* array of {@code java.security.cert.Certificate} should
|
||||
* be used instead. This method is subject to removal in
|
||||
* a future version of Java SE.
|
||||
*/
|
||||
@Deprecated
|
||||
@Deprecated(since="9", forRemoval=true)
|
||||
public javax.security.cert.X509Certificate [] getPeerCertificateChain()
|
||||
throws SSLPeerUnverifiedException;
|
||||
|
||||
|
@ -122,6 +122,14 @@ grant codeBase "jrt:/java.xml.bind" {
|
||||
permission java.util.PropertyPermission "*", "read";
|
||||
};
|
||||
|
||||
grant codeBase "jrt:/java.xml.crypto" {
|
||||
permission java.util.PropertyPermission "*", "read";
|
||||
permission java.security.SecurityPermission "putProviderProperty.XMLDSig";
|
||||
permission java.security.SecurityPermission "clearProviderProperties.XMLDSig";
|
||||
permission java.security.SecurityPermission "removeProviderProperty.XMLDSig";
|
||||
permission java.security.SecurityPermission "com.sun.org.apache.xml.internal.security.register";
|
||||
};
|
||||
|
||||
grant codeBase "jrt:/java.xml.ws" {
|
||||
permission java.lang.RuntimePermission "accessClassInPackage.com.sun.xml.internal.*";
|
||||
permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal";
|
||||
|
@ -74,8 +74,8 @@ struct ResourceHeader {
|
||||
* meaning that the resource is equivalent to the not compressed resource.
|
||||
* In each iteration, the name of the compressor located in the current header
|
||||
* is used to retrieve the associated instance of ImageDecompressor.
|
||||
* For example “zip” is the name of the compressor that compresses resources
|
||||
* using the zip algorithm. The ZipDecompressor class name is also “zip”.
|
||||
* For example "zip" is the name of the compressor that compresses resources
|
||||
* using the zip algorithm. The ZipDecompressor class name is also "zip".
|
||||
* ImageDecompressor instances are retrieved from a static array in which
|
||||
* they are registered.
|
||||
*/
|
||||
|
@ -101,7 +101,7 @@ typedef void (*JImageClose_t)(JImageFile* jimage);
|
||||
* Ex.
|
||||
* const char* package = (*JImagePackageToModule)(image, "java/lang");
|
||||
* tty->print_cr(package);
|
||||
* —> java.base
|
||||
* -> java.base
|
||||
*/
|
||||
|
||||
extern "C" const char * JIMAGE_PackageToModule(JImageFile* jimage, const char* package_name);
|
||||
@ -133,7 +133,7 @@ typedef JImageLocationRef(*JImageFindResource_t)(JImageFile* jimage,
|
||||
|
||||
|
||||
/*
|
||||
* JImageGetResource - Given an open image file (see JImageOpen), a resource’s
|
||||
* JImageGetResource - Given an open image file (see JImageOpen), a resource's
|
||||
* location information (see JImageFindResource), a buffer of appropriate
|
||||
* size and the size, retrieve the bytes associated with the
|
||||
* resource. If the size is less than the resource size then the read is truncated.
|
||||
@ -165,7 +165,7 @@ typedef jlong(*JImageGetResource_t)(JImageFile* jimage, JImageLocationRef locati
|
||||
* Ex.
|
||||
* bool ctw_visitor(JImageFile* jimage, const char* module_name, const char* version,
|
||||
* const char* package, const char* name, const char* extension, void* arg) {
|
||||
* if (strcmp(extension, “class”) == 0) {
|
||||
* if (strcmp(extension, "class") == 0) {
|
||||
* char path[JIMAGE_MAX_PATH];
|
||||
* Thread* THREAD = Thread::current();
|
||||
* jio_snprintf(path, JIMAGE_MAX_PATH - 1, "/%s/%s", package, name);
|
||||
|
@ -23,6 +23,11 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides interfaces and classes for transferring data between and
|
||||
* within applications.
|
||||
*/
|
||||
|
||||
module java.datatransfer {
|
||||
exports java.awt.datatransfer;
|
||||
exports sun.datatransfer to java.desktop;
|
||||
|
@ -1,253 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2016, 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 sun.lwawt.macosx;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.accessibility.Accessible;
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.accessibility.AccessibleRole;
|
||||
import javax.accessibility.AccessibleState;
|
||||
import javax.accessibility.AccessibleStateSet;
|
||||
import javax.swing.event.EventListenerList;
|
||||
|
||||
/**
|
||||
* <P>{@code AccessibilityEventMonitor} implements a PropertyChange listener
|
||||
* on every UI object that implements interface {@code Accessible} in the Java
|
||||
* Virtual Machine. The events captured by these listeners are made available
|
||||
* through listeners supported by {@code AccessibilityEventMonitor}.
|
||||
* With this, all the individual events on each of the UI object
|
||||
* instances are funneled into one set of PropertyChange listeners.
|
||||
*
|
||||
* This code is a subset of com.sun.java.accessibility.util.AccessibilityEventMonitor
|
||||
* which resides in module jdk.accessibility. Due to modularization the code in
|
||||
* this package, java.desktop, can not be dependent on code in jdk.accessibility.
|
||||
*/
|
||||
|
||||
class AccessibilityEventMonitor {
|
||||
|
||||
/**
|
||||
* The current list of registered {@link java.beans.PropertyChangeListener
|
||||
* PropertyChangeListener} classes.
|
||||
*
|
||||
* @see #addPropertyChangeListener
|
||||
*/
|
||||
private static final EventListenerList listenerList =
|
||||
new EventListenerList();
|
||||
|
||||
|
||||
/**
|
||||
* The actual listener that is installed on the component instances.
|
||||
* This listener calls the other registered listeners when an event
|
||||
* occurs. By doing things this way, the actual number of listeners
|
||||
* installed on a component instance is drastically reduced.
|
||||
*/
|
||||
private static final AccessibilityEventListener accessibilityListener =
|
||||
new AccessibilityEventListener();
|
||||
|
||||
/**
|
||||
* Adds the specified listener to receive all PropertyChange events on
|
||||
* each UI object instance in the Java Virtual Machine as they occur.
|
||||
* <P>Note: This listener is automatically added to all component
|
||||
* instances created after this method is called. In addition, it
|
||||
* is only added to UI object instances that support this listener type.
|
||||
*
|
||||
* @param l the listener to add
|
||||
* @param a the Accessible object to add the PropertyChangeListener to
|
||||
*/
|
||||
|
||||
static void addPropertyChangeListener(PropertyChangeListener l, Accessible a) {
|
||||
if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) {
|
||||
accessibilityListener.installListeners(a);
|
||||
}
|
||||
listenerList.add(PropertyChangeListener.class, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* AccessibilityEventListener is the class that does all the work for
|
||||
* AccessibilityEventMonitor. It is not intended for use by any other
|
||||
* class except AccessibilityEventMonitor.
|
||||
*/
|
||||
|
||||
private static class AccessibilityEventListener implements PropertyChangeListener {
|
||||
|
||||
/**
|
||||
* Installs PropertyChange listeners to the Accessible object, and its
|
||||
* children (so long as the object isn't of TRANSIENT state).
|
||||
*
|
||||
* @param a the Accessible object to add listeners to
|
||||
*/
|
||||
private void installListeners(Accessible a) {
|
||||
installListeners(a.getAccessibleContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs PropertyChange listeners to the AccessibleContext object,
|
||||
* and its * children (so long as the object isn't of TRANSIENT state).
|
||||
*
|
||||
* @param ac the AccessibleContext to add listeners to
|
||||
*/
|
||||
private void installListeners(AccessibleContext ac) {
|
||||
|
||||
if (ac != null) {
|
||||
AccessibleStateSet states = ac.getAccessibleStateSet();
|
||||
if (!states.contains(AccessibleState.TRANSIENT)) {
|
||||
ac.addPropertyChangeListener(this);
|
||||
/*
|
||||
* Don't add listeners to transient children. Components
|
||||
* with transient children should return an AccessibleStateSet
|
||||
* containing AccessibleState.MANAGES_DESCENDANTS. Components
|
||||
* may not explicitly return the MANAGES_DESCENDANTS state.
|
||||
* In this case, don't add listeners to the children of
|
||||
* lists, tables and trees.
|
||||
*/
|
||||
AccessibleStateSet set = ac.getAccessibleStateSet();
|
||||
if (set.contains(AccessibleState.MANAGES_DESCENDANTS)) {
|
||||
return;
|
||||
}
|
||||
AccessibleRole role = ac.getAccessibleRole();
|
||||
if ( role == AccessibleRole.LIST ||
|
||||
role == AccessibleRole.TREE ) {
|
||||
return;
|
||||
}
|
||||
if (role == AccessibleRole.TABLE) {
|
||||
// handle Oracle tables containing tables
|
||||
Accessible child = ac.getAccessibleChild(0);
|
||||
if (child != null) {
|
||||
AccessibleContext ac2 = child.getAccessibleContext();
|
||||
if (ac2 != null) {
|
||||
role = ac2.getAccessibleRole();
|
||||
if (role != null && role != AccessibleRole.TABLE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int count = ac.getAccessibleChildrenCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
Accessible child = ac.getAccessibleChild(i);
|
||||
if (child != null) {
|
||||
installListeners(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes PropertyChange listeners for the given Accessible object,
|
||||
* its children (so long as the object isn't of TRANSIENT state).
|
||||
*
|
||||
* @param a the Accessible object to remove listeners from
|
||||
*/
|
||||
private void removeListeners(Accessible a) {
|
||||
removeListeners(a.getAccessibleContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes PropertyChange listeners for the given AccessibleContext
|
||||
* object, its children (so long as the object isn't of TRANSIENT
|
||||
* state).
|
||||
*
|
||||
* @param a the Accessible object to remove listeners from
|
||||
*/
|
||||
private void removeListeners(AccessibleContext ac) {
|
||||
|
||||
if (ac != null) {
|
||||
// Listeners are not added to transient components.
|
||||
AccessibleStateSet states = ac.getAccessibleStateSet();
|
||||
if (!states.contains(AccessibleState.TRANSIENT)) {
|
||||
ac.removePropertyChangeListener(this);
|
||||
/*
|
||||
* Listeners are not added to transient children. Components
|
||||
* with transient children should return an AccessibleStateSet
|
||||
* containing AccessibleState.MANAGES_DESCENDANTS. Components
|
||||
* may not explicitly return the MANAGES_DESCENDANTS state.
|
||||
* In this case, don't remove listeners from the children of
|
||||
* lists, tables and trees.
|
||||
*/
|
||||
if (states.contains(AccessibleState.MANAGES_DESCENDANTS)) {
|
||||
return;
|
||||
}
|
||||
AccessibleRole role = ac.getAccessibleRole();
|
||||
if ( role == AccessibleRole.LIST ||
|
||||
role == AccessibleRole.TABLE ||
|
||||
role == AccessibleRole.TREE ) {
|
||||
return;
|
||||
}
|
||||
int count = ac.getAccessibleChildrenCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
Accessible child = ac.getAccessibleChild(i);
|
||||
if (child != null) {
|
||||
removeListeners(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent e) {
|
||||
// propogate the event
|
||||
Object[] listeners =
|
||||
AccessibilityEventMonitor.listenerList.getListenerList();
|
||||
for (int i = listeners.length-2; i>=0; i-=2) {
|
||||
if (listeners[i]==PropertyChangeListener.class) {
|
||||
((PropertyChangeListener)listeners[i+1]).propertyChange(e);
|
||||
}
|
||||
}
|
||||
|
||||
// handle childbirth/death
|
||||
String name = e.getPropertyName();
|
||||
if (name.compareTo(AccessibleContext.ACCESSIBLE_CHILD_PROPERTY) == 0) {
|
||||
Object oldValue = e.getOldValue();
|
||||
Object newValue = e.getNewValue();
|
||||
|
||||
if ((oldValue == null) ^ (newValue == null)) { // one null, not both
|
||||
if (oldValue != null) {
|
||||
// this Accessible is a child that's going away
|
||||
if (oldValue instanceof Accessible) {
|
||||
Accessible a = (Accessible) oldValue;
|
||||
removeListeners(a.getAccessibleContext());
|
||||
} else if (oldValue instanceof AccessibleContext) {
|
||||
removeListeners((AccessibleContext) oldValue);
|
||||
}
|
||||
} else if (newValue != null) {
|
||||
// this Accessible is a child was just born
|
||||
if (newValue instanceof Accessible) {
|
||||
Accessible a = (Accessible) newValue;
|
||||
installListeners(a.getAccessibleContext());
|
||||
} else if (newValue instanceof AccessibleContext) {
|
||||
installListeners((AccessibleContext) newValue);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.out.println("ERROR in usage of PropertyChangeEvents for: " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -285,7 +285,7 @@ class CAccessibility implements PropertyChangeListener {
|
||||
}
|
||||
|
||||
public static int getAccessibleIndexInParent(final Accessible a, final Component c) {
|
||||
if (a == null) return 0;
|
||||
if (a == null) return -1;
|
||||
|
||||
return invokeAndWait(new Callable<Integer>() {
|
||||
public Integer call() throws Exception {
|
||||
@ -468,6 +468,24 @@ class CAccessibility implements PropertyChangeListener {
|
||||
}, c);
|
||||
}
|
||||
|
||||
public static void requestSelection(final Accessible a, final Component c) {
|
||||
if (a == null) return;
|
||||
invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
AccessibleContext ac = a.getAccessibleContext();
|
||||
if (ac == null) return;
|
||||
int i = ac.getAccessibleIndexInParent();
|
||||
if (i == -1) return;
|
||||
Accessible parent = ac.getAccessibleParent();
|
||||
AccessibleContext pac = parent.getAccessibleContext();
|
||||
if (pac == null) return;
|
||||
AccessibleSelection as = pac.getAccessibleSelection();
|
||||
if (as == null) return;
|
||||
as.addAccessibleSelection(i);
|
||||
}
|
||||
}, c);
|
||||
}
|
||||
|
||||
public static Number getMaximumAccessibleValue(final Accessible a, final Component c) {
|
||||
if (a == null) return null;
|
||||
|
||||
@ -572,9 +590,57 @@ class CAccessibility implements PropertyChangeListener {
|
||||
if (a == null) return null;
|
||||
return invokeAndWait(new Callable<Object[]>() {
|
||||
public Object[] call() throws Exception {
|
||||
final ArrayList<Object> childrenAndRoles = new ArrayList<Object>();
|
||||
ArrayList<Object> childrenAndRoles = new ArrayList<Object>();
|
||||
_addChildren(a, whichChildren, allowIgnored, childrenAndRoles);
|
||||
|
||||
/* In the case of fetching a selection, need to check to see if
|
||||
* the active descendant is at the beginning of the list. If it
|
||||
* is not it needs to be moved to the beginning of the list so
|
||||
* VoiceOver will annouce it correctly. The list returned
|
||||
* from Java is always in order from top to bottom, but when shift
|
||||
* selecting downward (extending the list) or multi-selecting using
|
||||
* the VO keys control+option+command+return the active descendant
|
||||
* is not at the top of the list in the shift select down case and
|
||||
* may not be in the multi select case.
|
||||
*/
|
||||
if (whichChildren == JAVA_AX_SELECTED_CHILDREN) {
|
||||
if (!childrenAndRoles.isEmpty()) {
|
||||
AccessibleContext activeDescendantAC =
|
||||
CAccessible.getActiveDescendant(a);
|
||||
if (activeDescendantAC != null) {
|
||||
String activeDescendantName =
|
||||
activeDescendantAC.getAccessibleName();
|
||||
AccessibleRole activeDescendantRole =
|
||||
activeDescendantAC.getAccessibleRole();
|
||||
// Move active descendant to front of list.
|
||||
// List contains pairs of each selected item's
|
||||
// Accessible and AccessibleRole.
|
||||
ArrayList<Object> newArray = new ArrayList<Object>();
|
||||
int count = childrenAndRoles.size();
|
||||
Accessible currentAccessible = null;
|
||||
AccessibleContext currentAC = null;
|
||||
String currentName = null;
|
||||
AccessibleRole currentRole = null;
|
||||
for (int i = 0; i < count; i+=2) {
|
||||
// Is this the active descendant?
|
||||
currentAccessible = (Accessible)childrenAndRoles.get(i);
|
||||
currentAC = currentAccessible.getAccessibleContext();
|
||||
currentName = currentAC.getAccessibleName();
|
||||
currentRole = (AccessibleRole)childrenAndRoles.get(i+1);
|
||||
if ( currentName.equals(activeDescendantName) &&
|
||||
currentRole.equals(activeDescendantRole) ) {
|
||||
newArray.add(0, currentAccessible);
|
||||
newArray.add(1, currentRole);
|
||||
} else {
|
||||
newArray.add(currentAccessible);
|
||||
newArray.add(currentRole);
|
||||
}
|
||||
}
|
||||
childrenAndRoles = newArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((whichChildren < 0) || (whichChildren * 2 >= childrenAndRoles.size())) {
|
||||
return childrenAndRoles.toArray();
|
||||
}
|
||||
|
@ -37,7 +37,11 @@ import javax.swing.JSlider;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import sun.lwawt.macosx.CFRetainedResource;
|
||||
import static javax.accessibility.AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY;
|
||||
import static javax.accessibility.AccessibleContext.ACCESSIBLE_CARET_PROPERTY;
|
||||
import static javax.accessibility.AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY;
|
||||
import static javax.accessibility.AccessibleContext.ACCESSIBLE_TEXT_PROPERTY;
|
||||
|
||||
|
||||
class CAccessible extends CFRetainedResource implements Accessible {
|
||||
static Field getNativeAXResourceField() {
|
||||
@ -71,10 +75,13 @@ class CAccessible extends CFRetainedResource implements Accessible {
|
||||
|
||||
private static native void unregisterFromCocoaAXSystem(long ptr);
|
||||
private static native void valueChanged(long ptr);
|
||||
private static native void selectedTextChanged(long ptr);
|
||||
private static native void selectionChanged(long ptr);
|
||||
|
||||
private Accessible accessible;
|
||||
|
||||
private AccessibleContext activeDescendant;
|
||||
|
||||
private CAccessible(final Accessible accessible) {
|
||||
super(0L, true); // real pointer will be poked in by native
|
||||
|
||||
@ -98,9 +105,9 @@ class CAccessible extends CFRetainedResource implements Accessible {
|
||||
}
|
||||
|
||||
public void addNotificationListeners(Component c) {
|
||||
AXTextChangeNotifier listener = new AXTextChangeNotifier();
|
||||
if (c instanceof Accessible) {
|
||||
AccessibilityEventMonitor.addPropertyChangeListener(listener, (Accessible)c);
|
||||
AccessibleContext ac = ((Accessible)c).getAccessibleContext();
|
||||
ac.addPropertyChangeListener(new AXChangeNotifier());
|
||||
}
|
||||
if (c instanceof JProgressBar) {
|
||||
JProgressBar pb = (JProgressBar) c;
|
||||
@ -112,16 +119,23 @@ class CAccessible extends CFRetainedResource implements Accessible {
|
||||
}
|
||||
|
||||
|
||||
private class AXTextChangeNotifier implements PropertyChangeListener {
|
||||
private class AXChangeNotifier implements PropertyChangeListener {
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent e) {
|
||||
String name = e.getPropertyName();
|
||||
if ( ptr != 0 ) {
|
||||
if (name.compareTo(AccessibleContext.ACCESSIBLE_CARET_PROPERTY) == 0) {
|
||||
selectionChanged(ptr);
|
||||
} else if (name.compareTo(AccessibleContext.ACCESSIBLE_TEXT_PROPERTY) == 0 ) {
|
||||
if (name.compareTo(ACCESSIBLE_CARET_PROPERTY) == 0) {
|
||||
selectedTextChanged(ptr);
|
||||
} else if (name.compareTo(ACCESSIBLE_TEXT_PROPERTY) == 0 ) {
|
||||
valueChanged(ptr);
|
||||
} else if (name.compareTo(ACCESSIBLE_SELECTION_PROPERTY) == 0 ) {
|
||||
selectionChanged(ptr);
|
||||
} else if (name.compareTo(ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY) == 0 ) {
|
||||
Object nv = e.getNewValue();
|
||||
if (nv instanceof AccessibleContext) {
|
||||
activeDescendant = (AccessibleContext)nv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -137,4 +151,9 @@ class CAccessible extends CFRetainedResource implements Accessible {
|
||||
static Accessible getSwingAccessible(final Accessible a) {
|
||||
return (a instanceof CAccessible) ? ((CAccessible)a).accessible : a;
|
||||
}
|
||||
|
||||
static AccessibleContext getActiveDescendant(final Accessible a) {
|
||||
return (a instanceof CAccessible) ? ((CAccessible)a).activeDescendant : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -135,6 +135,7 @@ final class CPlatformResponder {
|
||||
int jkeyCode = KeyEvent.VK_UNDEFINED;
|
||||
int jkeyLocation = KeyEvent.KEY_LOCATION_UNKNOWN;
|
||||
boolean postsTyped = false;
|
||||
boolean spaceKeyTyped = false;
|
||||
|
||||
char testChar = KeyEvent.CHAR_UNDEFINED;
|
||||
boolean isDeadChar = (chars!= null && chars.length() == 0);
|
||||
@ -151,6 +152,11 @@ final class CPlatformResponder {
|
||||
} else {
|
||||
if (chars != null && chars.length() > 0) {
|
||||
testChar = chars.charAt(0);
|
||||
|
||||
//Check if String chars contains SPACE character.
|
||||
if (chars.trim().isEmpty()) {
|
||||
spaceKeyTyped = true;
|
||||
}
|
||||
}
|
||||
|
||||
char testCharIgnoringModifiers = charsIgnoringModifiers != null && charsIgnoringModifiers.length() > 0 ?
|
||||
@ -187,7 +193,7 @@ final class CPlatformResponder {
|
||||
NSEvent.nsToJavaEventType(eventType);
|
||||
}
|
||||
|
||||
char javaChar = NSEvent.nsToJavaChar(testChar, modifierFlags);
|
||||
char javaChar = NSEvent.nsToJavaChar(testChar, modifierFlags, spaceKeyTyped);
|
||||
// Some keys may generate a KEY_TYPED, but we can't determine
|
||||
// what that character is. That's likely a bug, but for now we
|
||||
// just check for CHAR_UNDEFINED.
|
||||
|
@ -254,7 +254,7 @@ final class NSEvent {
|
||||
* There is a small number of NS characters that need to be converted
|
||||
* into other characters before we pass them to AWT.
|
||||
*/
|
||||
static native char nsToJavaChar(char nsChar, int modifierFlags);
|
||||
static native char nsToJavaChar(char nsChar, int modifierFlags, boolean spaceKeyTyped);
|
||||
|
||||
static boolean isPopupTrigger(int jmodifiers) {
|
||||
final boolean isRightButtonDown = ((jmodifiers & InputEvent.BUTTON3_DOWN_MASK) != 0);
|
||||
|
@ -277,6 +277,16 @@ const nsKeyToJavaModifierTable[] =
|
||||
java_awt_event_InputEvent_CTRL_MASK,
|
||||
java_awt_event_KeyEvent_VK_CONTROL
|
||||
},
|
||||
{
|
||||
NSCommandKeyMask,
|
||||
//kCGSFlagsMaskAppleLeftCommandKey,
|
||||
//kCGSFlagsMaskAppleRightCommandKey,
|
||||
55,
|
||||
54,
|
||||
java_awt_event_InputEvent_META_DOWN_MASK,
|
||||
java_awt_event_InputEvent_META_MASK,
|
||||
java_awt_event_KeyEvent_VK_META
|
||||
},
|
||||
{
|
||||
NSAlternateKeyMask,
|
||||
//kCGSFlagsMaskAppleLeftAlternateKey,
|
||||
@ -295,16 +305,6 @@ const nsKeyToJavaModifierTable[] =
|
||||
java_awt_event_InputEvent_ALT_MASK | java_awt_event_InputEvent_ALT_GRAPH_MASK,
|
||||
java_awt_event_KeyEvent_VK_ALT | java_awt_event_KeyEvent_VK_ALT_GRAPH
|
||||
},
|
||||
{
|
||||
NSCommandKeyMask,
|
||||
//kCGSFlagsMaskAppleLeftCommandKey,
|
||||
//kCGSFlagsMaskAppleRightCommandKey,
|
||||
55,
|
||||
54,
|
||||
java_awt_event_InputEvent_META_DOWN_MASK,
|
||||
java_awt_event_InputEvent_META_MASK,
|
||||
java_awt_event_KeyEvent_VK_META
|
||||
},
|
||||
// NSNumericPadKeyMask
|
||||
{
|
||||
NSHelpKeyMask,
|
||||
@ -319,6 +319,7 @@ const nsKeyToJavaModifierTable[] =
|
||||
};
|
||||
|
||||
static BOOL leftAltKeyPressed;
|
||||
static BOOL altGRPressed = NO;
|
||||
|
||||
/*
|
||||
* Almost all unicode characters just go from NS to Java with no translation.
|
||||
@ -349,7 +350,7 @@ const charTable[] = {
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
unichar NsCharToJavaChar(unichar nsChar, NSUInteger modifiers)
|
||||
unichar NsCharToJavaChar(unichar nsChar, NSUInteger modifiers, BOOL spaceKeyTyped)
|
||||
{
|
||||
const struct _char *cur;
|
||||
// Mask off just the keyboard modifiers from the event modifier mask.
|
||||
@ -382,6 +383,11 @@ unichar NsCharToJavaChar(unichar nsChar, NSUInteger modifiers)
|
||||
return java_awt_event_KeyEvent_CHAR_UNDEFINED;
|
||||
}
|
||||
|
||||
// nsChar receives value 0 when SPACE key is typed.
|
||||
if (nsChar == 0 && spaceKeyTyped == YES) {
|
||||
return java_awt_event_KeyEvent_VK_SPACE;
|
||||
}
|
||||
|
||||
// otherwise return character unchanged
|
||||
return nsChar;
|
||||
}
|
||||
@ -554,20 +560,28 @@ NsKeyModifiersToJavaKeyInfo(NSUInteger nsFlags, unsigned short eventKeyCode,
|
||||
*/
|
||||
jint NsKeyModifiersToJavaModifiers(NSUInteger nsFlags, BOOL isExtMods)
|
||||
{
|
||||
jint javaModifiers = 0;
|
||||
const struct _nsKeyToJavaModifier* cur;
|
||||
jint javaModifiers = 0;
|
||||
const struct _nsKeyToJavaModifier* cur;
|
||||
|
||||
for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) {
|
||||
if ((cur->nsMask & nsFlags) != 0) {
|
||||
javaModifiers |= isExtMods ? cur->javaExtMask : cur->javaMask;
|
||||
if (cur->nsMask == NSAlternateKeyMask && leftAltKeyPressed == NO) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (cur = nsKeyToJavaModifierTable; cur->nsMask != 0; ++cur) {
|
||||
if ((cur->nsMask & nsFlags) != 0) {
|
||||
|
||||
if (cur->nsMask == NSAlternateKeyMask) {
|
||||
if (leftAltKeyPressed == YES) {
|
||||
javaModifiers |= isExtMods? cur->javaExtMask : cur->javaMask;
|
||||
if (altGRPressed == NO)
|
||||
break;
|
||||
} else {
|
||||
leftAltKeyPressed = YES;
|
||||
altGRPressed = YES;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
javaModifiers |= isExtMods ? cur->javaExtMask : cur->javaMask;
|
||||
}
|
||||
}
|
||||
|
||||
return javaModifiers;
|
||||
return javaModifiers;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -757,13 +771,13 @@ JNF_COCOA_EXIT(env);
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_lwawt_macosx_NSEvent_nsToJavaChar
|
||||
(JNIEnv *env, jclass cls, jchar nsChar, jint modifierFlags)
|
||||
(JNIEnv *env, jclass cls, jchar nsChar, jint modifierFlags, jboolean spaceKeyTyped)
|
||||
{
|
||||
jchar javaChar = 0;
|
||||
|
||||
JNF_COCOA_ENTER(env);
|
||||
|
||||
javaChar = NsCharToJavaChar(nsChar, modifierFlags);
|
||||
javaChar = NsCharToJavaChar(nsChar, modifierFlags, spaceKeyTyped);
|
||||
|
||||
JNF_COCOA_EXIT(env);
|
||||
|
||||
|
@ -261,27 +261,10 @@ Java_sun_lwawt_macosx_CRobot_keyEvent
|
||||
{
|
||||
CGKeyCode keyCode = GetCGKeyCode(javaKeyCode);
|
||||
|
||||
if ((javaKeyCode >= java_awt_event_KeyEvent_VK_0) &&
|
||||
(javaKeyCode <= java_awt_event_KeyEvent_VK_9))
|
||||
{
|
||||
AXUIElementRef elem = AXUIElementCreateSystemWide();
|
||||
AXUIElementPostKeyboardEvent(elem, (CGCharCode)0, keyCode, keyPressed);
|
||||
CFRelease(elem);
|
||||
} else {
|
||||
/*
|
||||
* JDK-8155740: AXUIElementPostKeyboardEvent posts correct key codes for
|
||||
* number keys whereas CGEventPost posts Numpad keys for corresponding
|
||||
* number key. Hence AXUIElementPostKeyboardEvent is used for posting
|
||||
* numbers and CGEventCreateKeyboardEvent/CGEventPost is used for other
|
||||
* keys.
|
||||
* Key code for modifier key is required to distinguish between ALT and
|
||||
* ALT-GR key for fixing issue 8155740.
|
||||
*/
|
||||
CGEventRef event = CGEventCreateKeyboardEvent(NULL, keyCode, keyPressed);
|
||||
if (event != NULL) {
|
||||
CGEventPost(kCGSessionEventTap, event);
|
||||
CFRelease(event);
|
||||
}
|
||||
CGEventRef event = CGEventCreateKeyboardEvent(NULL, keyCode, keyPressed);
|
||||
if (event != NULL) {
|
||||
CGEventPost(kCGSessionEventTap, event);
|
||||
CFRelease(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,16 +63,20 @@
|
||||
|
||||
jobject fCompLocal = (*env)->NewLocalRef(env, fComponent);
|
||||
if ((*env)->IsSameObject(env, fCompLocal, NULL)) {
|
||||
return @"unknown";
|
||||
return nil;
|
||||
}
|
||||
NSString *str = nil;
|
||||
jobject jstr = JNFCallStaticObjectMethod(env, jm_getAccessibleActionDescription, fAccessibleAction, fIndex, fCompLocal);
|
||||
jstring jstr = JNFCallStaticObjectMethod( env,
|
||||
jm_getAccessibleActionDescription,
|
||||
fAccessibleAction,
|
||||
fIndex,
|
||||
fCompLocal );
|
||||
if (jstr != NULL) {
|
||||
NSString *str = JNFJavaToNSString(env, jstr); // AWT_THREADING Safe (AWTRunLoopMode)
|
||||
str = JNFJavaToNSString(env, jstr); // AWT_THREADING Safe (AWTRunLoopMode)
|
||||
(*env)->DeleteLocalRef(env, jstr);
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, fCompLocal);
|
||||
return str == nil ? @"unknown" : str;
|
||||
return str;
|
||||
}
|
||||
|
||||
- (void)perform
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, 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
|
||||
@ -55,6 +55,7 @@ BOOL containsAxState(JNIEnv *env, jobject axContext, jobject axState, jobject co
|
||||
BOOL isVertical(JNIEnv *env, jobject axContext, jobject component);
|
||||
BOOL isHorizontal(JNIEnv *env, jobject axContext, jobject component);
|
||||
BOOL isShowing(JNIEnv *env, jobject axContext, jobject component);
|
||||
BOOL isSelectable(JNIEnv *env, jobject axContext, jobject component);
|
||||
NSPoint getAxComponentLocationOnScreen(JNIEnv *env, jobject axComponent, jobject component);
|
||||
jint getAxTextCharCount(JNIEnv *env, jobject axText, jobject component);
|
||||
|
||||
|
@ -151,6 +151,18 @@ BOOL isShowing(JNIEnv *env, jobject axContext, jobject component)
|
||||
return showing;
|
||||
}
|
||||
|
||||
BOOL isSelectable(JNIEnv *env, jobject axContext, jobject component)
|
||||
{
|
||||
static JNF_STATIC_MEMBER_CACHE( jm_SELECTABLE,
|
||||
sjc_AccessibleState,
|
||||
"SELECTABLE",
|
||||
"Ljavax/accessibility/AccessibleState;" );
|
||||
jobject axSelectableState = JNFGetStaticObjectField(env, jm_SELECTABLE);
|
||||
BOOL selectable = containsAxState(env, axContext, axSelectableState, component);
|
||||
(*env)->DeleteLocalRef(env, axSelectableState);
|
||||
return selectable;
|
||||
}
|
||||
|
||||
NSPoint getAxComponentLocationOnScreen(JNIEnv *env, jobject axComponent, jobject component)
|
||||
{
|
||||
static JNF_STATIC_MEMBER_CACHE(jm_getLocationOnScreen, sjc_CAccessibility, "getLocationOnScreen", "(Ljavax/accessibility/AccessibleComponent;Ljava/awt/Component;)Ljava/awt/Point;");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, 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
|
||||
@ -50,6 +50,7 @@
|
||||
- (id)initWithParent:(NSObject*)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withView:(NSView *)view withJavaRole:(NSString *)javaRole;
|
||||
- (void)unregisterFromCocoaAXSystem;
|
||||
- (void)postValueChanged;
|
||||
- (void)postSelectedTextChanged;
|
||||
- (void)postSelectionChanged;
|
||||
- (BOOL)isEqual:(id)anObject;
|
||||
- (BOOL)isAccessibleWithEnv:(JNIEnv *)env forAccessible:(jobject)accessible;
|
||||
@ -71,6 +72,7 @@
|
||||
- (NSString *)javaRole;
|
||||
- (BOOL)isMenu;
|
||||
- (BOOL)isSelected:(JNIEnv *)env;
|
||||
- (BOOL)isSelectable:(JNIEnv *)env;
|
||||
- (BOOL)isVisible:(JNIEnv *)env;
|
||||
|
||||
// attribute names
|
||||
@ -85,6 +87,8 @@
|
||||
- (NSArray *)accessibilityChildrenAttribute;
|
||||
- (BOOL)accessibilityIsChildrenAttributeSettable;
|
||||
- (NSUInteger)accessibilityIndexOfChild:(id)child;
|
||||
- (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute
|
||||
index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
|
||||
- (NSNumber *)accessibilityEnabledAttribute;
|
||||
- (BOOL)accessibilityIsEnabledAttributeSettable;
|
||||
- (NSNumber *)accessibilityFocusedAttribute;
|
||||
@ -92,6 +96,8 @@
|
||||
- (void)accessibilitySetFocusedAttribute:(id)value;
|
||||
- (NSString *)accessibilityHelpAttribute;
|
||||
- (BOOL)accessibilityIsHelpAttributeSettable;
|
||||
- (NSValue *)accessibilityIndexAttribute;
|
||||
- (BOOL)accessibilityIsIndexAttributeSettable;
|
||||
- (id)accessibilityMaxValueAttribute;
|
||||
- (BOOL)accessibilityIsMaxValueAttributeSettable;
|
||||
- (id)accessibilityMinValueAttribute;
|
||||
@ -108,6 +114,9 @@
|
||||
- (BOOL)accessibilityIsRoleDescriptionAttributeSettable;
|
||||
- (NSArray *)accessibilitySelectedChildrenAttribute;
|
||||
- (BOOL)accessibilityIsSelectedChildrenAttributeSettable;
|
||||
- (NSNumber *)accessibilitySelectedAttribute;
|
||||
- (BOOL)accessibilityIsSelectedAttributeSettable;
|
||||
- (void)accessibilitySetSelectedAttribute:(id)value;
|
||||
- (NSValue *)accessibilitySizeAttribute;
|
||||
- (BOOL)accessibilityIsSizeAttributeSettable;
|
||||
- (NSString *)accessibilitySubroleAttribute;
|
||||
|
@ -201,12 +201,18 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
NSAccessibilityPostNotification(self, NSAccessibilityValueChangedNotification);
|
||||
}
|
||||
|
||||
- (void)postSelectionChanged
|
||||
- (void)postSelectedTextChanged
|
||||
{
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
NSAccessibilityPostNotification(self, NSAccessibilitySelectedTextChangedNotification);
|
||||
}
|
||||
|
||||
- (void)postSelectionChanged
|
||||
{
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
NSAccessibilityPostNotification(self, NSAccessibilitySelectedChildrenChangedNotification);
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)anObject
|
||||
{
|
||||
if (![anObject isKindOfClass:[self class]]) return NO;
|
||||
@ -225,7 +231,7 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
{
|
||||
if (sAttributeNamesForRoleCache == nil) {
|
||||
sAttributeNamesLOCK = [[NSObject alloc] init];
|
||||
sAttributeNamesForRoleCache = [[NSMutableDictionary alloc] initWithCapacity:10];
|
||||
sAttributeNamesForRoleCache = [[NSMutableDictionary alloc] initWithCapacity:60];
|
||||
}
|
||||
|
||||
if (sRoles == nil) {
|
||||
@ -281,6 +287,7 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
|
||||
+ (NSArray *)childrenOfParent:(JavaComponentAccessibility *)parent withEnv:(JNIEnv *)env withChildrenCode:(NSInteger)whichChildren allowIgnored:(BOOL)allowIgnored
|
||||
{
|
||||
if (parent->fAccessible == NULL) return nil;
|
||||
jobjectArray jchildrenAndRoles = (jobjectArray)JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, parent->fAccessible, parent->fComponent, whichChildren, allowIgnored); // AWT_THREADING Safe (AWTRunLoop)
|
||||
if (jchildrenAndRoles == NULL) return nil;
|
||||
|
||||
@ -370,7 +377,7 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
{
|
||||
static JNF_STATIC_MEMBER_CACHE(jm_getInitialAttributeStates, sjc_CAccessibility, "getInitialAttributeStates", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[Z");
|
||||
|
||||
NSMutableArray *attributeNames = [NSMutableArray arrayWithCapacity:10];
|
||||
NSMutableArray *attributeNames = [NSMutableArray arrayWithCapacity:20];
|
||||
[attributeNames retain];
|
||||
|
||||
// all elements respond to parent, role, role description, window, topLevelUIElement, help
|
||||
@ -449,6 +456,12 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
// children
|
||||
if (attributeStatesArray[6]) {
|
||||
[attributeNames addObject:NSAccessibilityChildrenAttribute];
|
||||
if ([javaRole isEqualToString:@"list"]) {
|
||||
[attributeNames addObject:NSAccessibilitySelectedChildrenAttribute];
|
||||
[attributeNames addObject:NSAccessibilityVisibleChildrenAttribute];
|
||||
}
|
||||
// Just above, the below mentioned support has been added back in for lists.
|
||||
// However, the following comments may still be useful for future fixes.
|
||||
// [attributeNames addObject:NSAccessibilitySelectedChildrenAttribute];
|
||||
// [attributeNames addObject:NSAccessibilityVisibleChildrenAttribute];
|
||||
//According to AXRoles.txt:
|
||||
@ -567,6 +580,14 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
return isChildSelected(env, ((JavaComponentAccessibility *)[self parent])->fAccessible, fIndex, fComponent);
|
||||
}
|
||||
|
||||
- (BOOL)isSelectable:(JNIEnv *)env
|
||||
{
|
||||
jobject axContext = [self axContextWithEnv:env];
|
||||
BOOL selectable = isSelectable(env, axContext, fComponent);
|
||||
(*env)->DeleteLocalRef(env, axContext);
|
||||
return selectable;
|
||||
}
|
||||
|
||||
- (BOOL)isVisible:(JNIEnv *)env
|
||||
{
|
||||
if (fIndex == -1) {
|
||||
@ -586,18 +607,32 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
|
||||
@synchronized(sAttributeNamesLOCK) {
|
||||
NSString *javaRole = [self javaRole];
|
||||
NSArray *names = (NSArray *)[sAttributeNamesForRoleCache objectForKey:javaRole];
|
||||
if (names != nil) return names;
|
||||
|
||||
names = [self initializeAttributeNamesWithEnv:env];
|
||||
if (names != nil) {
|
||||
NSArray *names =
|
||||
(NSArray *)[sAttributeNamesForRoleCache objectForKey:javaRole];
|
||||
if (names == nil) {
|
||||
names = [self initializeAttributeNamesWithEnv:env];
|
||||
#ifdef JAVA_AX_DEBUG
|
||||
NSLog(@"Initializing: %s for %@: %@", __FUNCTION__, javaRole, names);
|
||||
#endif
|
||||
[sAttributeNamesForRoleCache setObject:names forKey:javaRole];
|
||||
return names;
|
||||
}
|
||||
}
|
||||
// The above set of attributes is immutable per role, but some objects, if
|
||||
// they are the child of a list, need to add the selected and index attributes.
|
||||
id myParent = [self accessibilityParentAttribute];
|
||||
if ([myParent isKindOfClass:[JavaComponentAccessibility class]]) {
|
||||
NSString *parentRole = [(JavaComponentAccessibility *)myParent javaRole];
|
||||
if ([parentRole isEqualToString:@"list"]) {
|
||||
NSMutableArray *moreNames =
|
||||
[[NSMutableArray alloc] initWithCapacity: [names count] + 2];
|
||||
[moreNames addObjectsFromArray: names];
|
||||
[moreNames addObject:NSAccessibilitySelectedAttribute];
|
||||
[moreNames addObject:NSAccessibilityIndexAttribute];
|
||||
return moreNames;
|
||||
}
|
||||
}
|
||||
return names;
|
||||
|
||||
} // end @synchronized
|
||||
|
||||
#ifdef JAVA_AX_DEBUG
|
||||
NSLog(@"Warning in %s: could not find attribute names for role: %@", __FUNCTION__, [self javaRole]);
|
||||
@ -656,7 +691,10 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
- (NSArray *)accessibilityChildrenAttribute
|
||||
{
|
||||
JNIEnv* env = [ThreadUtilities getJNIEnv];
|
||||
NSArray *children = [JavaComponentAccessibility childrenOfParent:self withEnv:env withChildrenCode:JAVA_AX_VISIBLE_CHILDREN allowIgnored:NO];
|
||||
NSArray *children = [JavaComponentAccessibility childrenOfParent:self
|
||||
withEnv:env
|
||||
withChildrenCode:JAVA_AX_ALL_CHILDREN
|
||||
allowIgnored:NO];
|
||||
|
||||
NSArray *value = nil;
|
||||
if ([children count] > 0) {
|
||||
@ -680,7 +718,12 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
return [super accessibilityIndexOfChild:child];
|
||||
}
|
||||
|
||||
return JNFCallStaticIntMethod([ThreadUtilities getJNIEnv], sjm_getAccessibleIndexInParent, ((JavaComponentAccessibility *)child)->fAccessible, ((JavaComponentAccessibility *)child)->fComponent);
|
||||
jint returnValue =
|
||||
JNFCallStaticIntMethod( [ThreadUtilities getJNIEnv],
|
||||
sjm_getAccessibleIndexInParent,
|
||||
((JavaComponentAccessibility *)child)->fAccessible,
|
||||
((JavaComponentAccessibility *)child)->fComponent );
|
||||
return (returnValue == -1) ? NSNotFound : returnValue;
|
||||
}
|
||||
|
||||
// Without this optimization accessibilityChildrenAttribute is called in order to get the entire array of children.
|
||||
@ -754,7 +797,7 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
|
||||
jobject val = JNFCallStaticObjectMethod(env, sjm_getAccessibleDescription, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
|
||||
if (val == NULL) {
|
||||
return @"unknown";
|
||||
return nil;
|
||||
}
|
||||
NSString* str = JNFJavaToNSString(env, val);
|
||||
(*env)->DeleteLocalRef(env, val);
|
||||
@ -766,6 +809,18 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSValue *)accessibilityIndexAttribute
|
||||
{
|
||||
NSInteger index = fIndex;
|
||||
NSValue *returnValue = [NSValue value:&index withObjCType:@encode(NSInteger)];
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityIsIndexAttributeSettable
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Element's maximum value (id)
|
||||
- (id)accessibilityMaxValueAttribute
|
||||
{
|
||||
@ -939,6 +994,33 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
return NO; // cmcnote: actually it should be. so need to write accessibilitySetSelectedChildrenAttribute also
|
||||
}
|
||||
|
||||
- (NSNumber *)accessibilitySelectedAttribute
|
||||
{
|
||||
return [NSNumber numberWithBool:[self isSelected:[ThreadUtilities getJNIEnv]]];
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityIsSelectedAttributeSettable
|
||||
{
|
||||
if ([self isSelectable:[ThreadUtilities getJNIEnv]]) {
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)accessibilitySetSelectedAttribute:(id)value
|
||||
{
|
||||
static JNF_STATIC_MEMBER_CACHE( jm_requestSelection,
|
||||
sjc_CAccessibility,
|
||||
"requestSelection",
|
||||
"(Ljavax/accessibility/Accessible;Ljava/awt/Component;)V" );
|
||||
|
||||
if ([(NSNumber*)value boolValue]) {
|
||||
JNIEnv* env = [ThreadUtilities getJNIEnv];
|
||||
JNFCallStaticVoidMethod(env, jm_requestSelection, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
|
||||
}
|
||||
}
|
||||
|
||||
// Element size (NSValue)
|
||||
- (NSValue *)accessibilitySizeAttribute {
|
||||
JNIEnv* env = [ThreadUtilities getJNIEnv];
|
||||
@ -1005,7 +1087,7 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
|
||||
jobject val = JNFCallStaticObjectMethod(env, sjm_getAccessibleName, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
|
||||
if (val == NULL) {
|
||||
return @"unknown";
|
||||
return nil;
|
||||
}
|
||||
NSString* str = JNFJavaToNSString(env, val);
|
||||
(*env)->DeleteLocalRef(env, val);
|
||||
@ -1210,14 +1292,11 @@ static NSObject *sAttributeNamesLOCK = nil;
|
||||
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessibility_focusChanged
|
||||
(JNIEnv *env, jobject jthis)
|
||||
{
|
||||
|
||||
JNF_COCOA_ENTER(env);
|
||||
[ThreadUtilities performOnMainThread:@selector(postFocusChanged:) on:[JavaComponentAccessibility class] withObject:nil waitUntilDone:NO];
|
||||
JNF_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_CAccessible
|
||||
* Method: valueChanged
|
||||
@ -1231,6 +1310,22 @@ JNF_COCOA_ENTER(env);
|
||||
JNF_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_CAccessible
|
||||
* Method: selectedTextChanged
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_selectedTextChanged
|
||||
(JNIEnv *env, jclass jklass, jlong element)
|
||||
{
|
||||
JNF_COCOA_ENTER(env);
|
||||
[ThreadUtilities performOnMainThread:@selector(postSelectedTextChanged)
|
||||
on:(JavaComponentAccessibility *)jlong_to_ptr(element)
|
||||
withObject:nil
|
||||
waitUntilDone:NO];
|
||||
JNF_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_CAccessible
|
||||
* Method: selectionChanged
|
||||
@ -1244,7 +1339,6 @@ JNF_COCOA_ENTER(env);
|
||||
JNF_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_CAccessible
|
||||
* Method: unregisterFromCocoaAXSystem
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016, 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
|
||||
@ -60,6 +60,4 @@
|
||||
- (NSValue *)accessibilityRangeForPositionAttributeForParameter:(id)parameter;
|
||||
- (NSValue *)accessibilityRangeForIndexAttributeForParameter:(id)parameter;
|
||||
|
||||
// actions
|
||||
- (NSDictionary *)getActions:(JNIEnv *)env;
|
||||
@end
|
||||
|
@ -427,13 +427,15 @@ NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) {
|
||||
return javaIntArrayToNSRangeValue(env, axTextRange);
|
||||
}
|
||||
|
||||
- (NSDictionary *)getActions:(JNIEnv *)env {
|
||||
// cmcnote: this isn't correct; text can have actions. Not yet implemented. radr://3941691
|
||||
// Editable text has AXShowMenu. Textfields have AXConfirm. Static text has no actions.
|
||||
#ifdef JAVA_AX_DEBUG
|
||||
NSLog(@"Not yet implemented: %s\n", __FUNCTION__);
|
||||
#endif
|
||||
return nil;
|
||||
}
|
||||
/*
|
||||
* - (NSDictionary *)getActions:(JNIEnv *)env { ... }
|
||||
*
|
||||
* In the future, possibly add support: Editable text has AXShowMenu.
|
||||
* Textfields have AXConfirm.
|
||||
*
|
||||
* Note: JLabels (static text) in JLists have a press/click selection action
|
||||
* which is currently handled in superclass JavaComponentAccessibility.
|
||||
* If function is added here be sure to use [super getActions:env] for JLabels.
|
||||
*/
|
||||
|
||||
@end
|
||||
|
@ -1339,14 +1339,14 @@ class GTKPainter extends SynthPainter {
|
||||
Graphics g, int state, int x, int y, int w, int h) {
|
||||
ENGINE.paintExpander(g, context, Region.TREE,
|
||||
GTKLookAndFeel.synthStateToGTKState(context.getRegion(), state),
|
||||
ExpanderStyle.EXPANDED, "treeview", x, y, w, h);
|
||||
ExpanderStyle.EXPANDED, "expander", x, y, w, h);
|
||||
}
|
||||
|
||||
public void paintTreeCollapsedIcon(SynthContext context,
|
||||
Graphics g, int state, int x, int y, int w, int h) {
|
||||
ENGINE.paintExpander(g, context, Region.TREE,
|
||||
GTKLookAndFeel.synthStateToGTKState(context.getRegion(), state),
|
||||
ExpanderStyle.COLLAPSED, "treeview", x, y, w, h);
|
||||
ExpanderStyle.COLLAPSED, "expander", x, y, w, h);
|
||||
}
|
||||
|
||||
public void paintCheckBoxIcon(SynthContext context,
|
||||
|
@ -854,6 +854,12 @@ class GTKStyle extends SynthStyle implements GTKConstants {
|
||||
return indicatorSpacing + focusSize + focusPad;
|
||||
} else if (GTKLookAndFeel.is3() && "ComboBox.forceOpaque".equals(key)) {
|
||||
return true;
|
||||
} else if ("Tree.expanderSize".equals(key)) {
|
||||
Object value = getClassSpecificValue("expander-size");
|
||||
if (value instanceof Integer) {
|
||||
return (Integer)value + 4;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Is it a stock icon ?
|
||||
@ -1136,7 +1142,6 @@ class GTKStyle extends SynthStyle implements GTKConstants {
|
||||
CLASS_SPECIFIC_MAP.put("Slider.thumbWidth", "slider-length");
|
||||
CLASS_SPECIFIC_MAP.put("Slider.trackBorder", "trough-border");
|
||||
CLASS_SPECIFIC_MAP.put("SplitPane.size", "handle-size");
|
||||
CLASS_SPECIFIC_MAP.put("Tree.expanderSize", "expander-size");
|
||||
CLASS_SPECIFIC_MAP.put("ScrollBar.thumbHeight", "slider-width");
|
||||
CLASS_SPECIFIC_MAP.put("ScrollBar.width", "slider-width");
|
||||
CLASS_SPECIFIC_MAP.put("TextArea.caretForeground", "cursor-color");
|
||||
|
@ -1013,8 +1013,8 @@ public class Desktop {
|
||||
* @param file the file
|
||||
* @return returns true if successfully moved the file to the trash.
|
||||
* @throws SecurityException If a security manager exists and its
|
||||
* {@link SecurityManager#checkWrite(java.lang.String)} method
|
||||
* denies write access to the file
|
||||
* {@link SecurityManager#checkDelete(java.lang.String)} method
|
||||
* denies deletion of the file
|
||||
* @throws UnsupportedOperationException if the current platform
|
||||
* does not support the {@link Desktop.Action#MOVE_TO_TRASH} action
|
||||
* @throws NullPointerException if {@code file} is {@code null}
|
||||
|
@ -1813,35 +1813,31 @@ public class Font implements java.io.Serializable
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj != null) {
|
||||
try {
|
||||
Font font = (Font)obj;
|
||||
if (size == font.size &&
|
||||
style == font.style &&
|
||||
nonIdentityTx == font.nonIdentityTx &&
|
||||
hasLayoutAttributes == font.hasLayoutAttributes &&
|
||||
pointSize == font.pointSize &&
|
||||
name.equals(font.name)) {
|
||||
if (obj instanceof Font) {
|
||||
Font font = (Font)obj;
|
||||
if (size == font.size &&
|
||||
style == font.style &&
|
||||
nonIdentityTx == font.nonIdentityTx &&
|
||||
hasLayoutAttributes == font.hasLayoutAttributes &&
|
||||
pointSize == font.pointSize &&
|
||||
name.equals(font.name)) {
|
||||
|
||||
/* 'values' is usually initialized lazily, except when
|
||||
* the font is constructed from a Map, or derived using
|
||||
* a Map or other values. So if only one font has
|
||||
* the field initialized we need to initialize it in
|
||||
* the other instance and compare.
|
||||
*/
|
||||
if (values == null) {
|
||||
if (font.values == null) {
|
||||
return true;
|
||||
} else {
|
||||
return getAttributeValues().equals(font.values);
|
||||
}
|
||||
/* 'values' is usually initialized lazily, except when
|
||||
* the font is constructed from a Map, or derived using
|
||||
* a Map or other values. So if only one font has
|
||||
* the field initialized we need to initialize it in
|
||||
* the other instance and compare.
|
||||
*/
|
||||
if (values == null) {
|
||||
if (font.values == null) {
|
||||
return true;
|
||||
} else {
|
||||
return values.equals(font.getAttributeValues());
|
||||
return getAttributeValues().equals(font.values);
|
||||
}
|
||||
} else {
|
||||
return values.equals(font.getAttributeValues());
|
||||
}
|
||||
}
|
||||
catch (ClassCastException e) {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ public class Taskbar {
|
||||
*
|
||||
* Some platforms do not support string values and accept only integer
|
||||
* values. In this case, pass an integer represented as a string as parameter.
|
||||
* This can be tested by {@code Feature.ICON_BADGE_STRING} and
|
||||
* This can be tested by {@code Feature.ICON_BADGE_TEXT} and
|
||||
* {@code Feature.ICON_BADGE_NUMBER}.
|
||||
*
|
||||
* Passing {@code null} as parameter hides the badge.
|
||||
@ -364,7 +364,8 @@ public class Taskbar {
|
||||
* @throws SecurityException if a security manager exists and it denies the
|
||||
* {@code AWTPermission("showWindowWithoutWarningBanner")} permission.
|
||||
* @throws UnsupportedOperationException if the current platform
|
||||
* does not support the {@link Taskbar.Feature#ICON_BADGE_NUMBER} feature
|
||||
* does not support the {@link Taskbar.Feature#ICON_BADGE_NUMBER}
|
||||
* or {@link Taskbar.Feature#ICON_BADGE_TEXT} feature
|
||||
*/
|
||||
public void setIconBadge(final String badge) {
|
||||
checkAWTPermission();
|
||||
|
@ -1388,9 +1388,7 @@ public abstract class Toolkit {
|
||||
// ensure that the proper libraries are loaded
|
||||
loadLibraries();
|
||||
initAssistiveTechnologies();
|
||||
if (!GraphicsEnvironment.isHeadless()) {
|
||||
initIDs();
|
||||
}
|
||||
initIDs();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -168,6 +168,9 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
|
||||
// Flag to ensure the we don't get multiple ActionEvents on item selection.
|
||||
private boolean selectingItem = false;
|
||||
|
||||
// Flag to indicate UI update is in progress
|
||||
private transient boolean updateInProgress;
|
||||
|
||||
/**
|
||||
* Creates a <code>JComboBox</code> that takes its items from an
|
||||
* existing <code>ComboBoxModel</code>. Since the
|
||||
@ -268,11 +271,18 @@ implements ItemSelectable,ListDataListener,ActionListener, Accessible {
|
||||
* @see JComponent#updateUI
|
||||
*/
|
||||
public void updateUI() {
|
||||
setUI((ComboBoxUI)UIManager.getUI(this));
|
||||
if (!updateInProgress) {
|
||||
updateInProgress = true;
|
||||
try {
|
||||
setUI((ComboBoxUI)UIManager.getUI(this));
|
||||
|
||||
ListCellRenderer<? super E> renderer = getRenderer();
|
||||
if (renderer instanceof Component) {
|
||||
SwingUtilities.updateComponentTreeUI((Component)renderer);
|
||||
ListCellRenderer<? super E> renderer = getRenderer();
|
||||
if (renderer instanceof Component) {
|
||||
SwingUtilities.updateComponentTreeUI((Component)renderer);
|
||||
}
|
||||
} finally {
|
||||
updateInProgress = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2016, 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
|
||||
@ -337,6 +337,11 @@ public class JList<E> extends JComponent implements Scrollable, Accessible
|
||||
*/
|
||||
private transient DropLocation dropLocation;
|
||||
|
||||
/**
|
||||
* Flag to indicate UI update is in progress
|
||||
*/
|
||||
private transient boolean updateInProgress;
|
||||
|
||||
/**
|
||||
* A subclass of <code>TransferHandler.DropLocation</code> representing
|
||||
* a drop location for a <code>JList</code>.
|
||||
@ -531,11 +536,18 @@ public class JList<E> extends JComponent implements Scrollable, Accessible
|
||||
* @see SwingUtilities#updateComponentTreeUI
|
||||
*/
|
||||
public void updateUI() {
|
||||
setUI((ListUI)UIManager.getUI(this));
|
||||
if (!updateInProgress) {
|
||||
updateInProgress = true;
|
||||
try {
|
||||
setUI((ListUI)UIManager.getUI(this));
|
||||
|
||||
ListCellRenderer<? super E> renderer = getCellRenderer();
|
||||
if (renderer instanceof Component) {
|
||||
SwingUtilities.updateComponentTreeUI((Component)renderer);
|
||||
ListCellRenderer<? super E> renderer = getCellRenderer();
|
||||
if (renderer instanceof Component) {
|
||||
SwingUtilities.updateComponentTreeUI((Component)renderer);
|
||||
}
|
||||
} finally {
|
||||
updateInProgress = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3046,7 +3058,7 @@ public class JList<E> extends JComponent implements Scrollable, Accessible
|
||||
public Accessible getAccessibleAt(Point p) {
|
||||
int i = locationToIndex(p);
|
||||
if (i >= 0) {
|
||||
return new AccessibleJListChild(JList.this, i);
|
||||
return new ActionableAccessibleJListChild(JList.this, i);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -3073,7 +3085,7 @@ public class JList<E> extends JComponent implements Scrollable, Accessible
|
||||
if (i >= getModel().getSize()) {
|
||||
return null;
|
||||
} else {
|
||||
return new AccessibleJListChild(JList.this, i);
|
||||
return new ActionableAccessibleJListChild(JList.this, i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3178,7 +3190,7 @@ public class JList<E> extends JComponent implements Scrollable, Accessible
|
||||
protected class AccessibleJListChild extends AccessibleContext
|
||||
implements Accessible, AccessibleComponent {
|
||||
private JList<E> parent = null;
|
||||
private int indexInParent;
|
||||
int indexInParent;
|
||||
private Component component = null;
|
||||
private AccessibleContext accessibleContext = null;
|
||||
private ListModel<E> listModel;
|
||||
@ -3203,7 +3215,7 @@ public class JList<E> extends JComponent implements Scrollable, Accessible
|
||||
return getComponentAtIndex(indexInParent);
|
||||
}
|
||||
|
||||
private AccessibleContext getCurrentAccessibleContext() {
|
||||
AccessibleContext getCurrentAccessibleContext() {
|
||||
Component c = getComponentAtIndex(indexInParent);
|
||||
if (c instanceof Accessible) {
|
||||
return c.getAccessibleContext();
|
||||
@ -3369,10 +3381,6 @@ public class JList<E> extends JComponent implements Scrollable, Accessible
|
||||
}
|
||||
}
|
||||
|
||||
public AccessibleAction getAccessibleAction() {
|
||||
return getCurrentAccessibleContext().getAccessibleAction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the AccessibleComponent associated with this object. In the
|
||||
* implementation of the Java Accessibility API for this class,
|
||||
@ -3587,7 +3595,13 @@ public class JList<E> extends JComponent implements Scrollable, Accessible
|
||||
|
||||
public Point getLocationOnScreen() {
|
||||
if (parent != null) {
|
||||
Point listLocation = parent.getLocationOnScreen();
|
||||
Point listLocation;
|
||||
try {
|
||||
listLocation = parent.getLocationOnScreen();
|
||||
} catch (IllegalComponentStateException e) {
|
||||
// This can happen if the component isn't visisble
|
||||
return null;
|
||||
}
|
||||
Point componentLocation = parent.indexToLocation(indexInParent);
|
||||
if (componentLocation != null) {
|
||||
componentLocation.translate(listLocation.x, listLocation.y);
|
||||
@ -3728,6 +3742,57 @@ public class JList<E> extends JComponent implements Scrollable, Accessible
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
} // inner class AccessibleJListChild
|
||||
|
||||
private class ActionableAccessibleJListChild
|
||||
extends AccessibleJListChild
|
||||
implements AccessibleAction {
|
||||
|
||||
ActionableAccessibleJListChild(JList<E> parent, int indexInParent) {
|
||||
super(parent, indexInParent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibleAction getAccessibleAction() {
|
||||
AccessibleContext ac = getCurrentAccessibleContext();
|
||||
if (ac == null) {
|
||||
return null;
|
||||
} else {
|
||||
AccessibleAction aa = ac.getAccessibleAction();
|
||||
if (aa != null) {
|
||||
return aa;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doAccessibleAction(int i) {
|
||||
if (i == 0) {
|
||||
JList.this.setSelectedIndex(indexInParent);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessibleActionDescription(int i) {
|
||||
if (i == 0) {
|
||||
return UIManager.getString("AbstractButton.clickText");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAccessibleActionCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // inner class ActionableAccessibleJListChild
|
||||
|
||||
} // inner class AccessibleJList
|
||||
}
|
||||
|
@ -454,6 +454,11 @@ public class JTable extends JComponent implements TableModelListener, Scrollable
|
||||
*/
|
||||
private transient DropLocation dropLocation;
|
||||
|
||||
/**
|
||||
* Flag to indicate UI update is in progress
|
||||
*/
|
||||
private transient boolean updateInProgress;
|
||||
|
||||
/**
|
||||
* A subclass of <code>TransferHandler.DropLocation</code> representing
|
||||
* a drop location for a <code>JTable</code>.
|
||||
@ -3621,36 +3626,46 @@ public class JTable extends JComponent implements TableModelListener, Scrollable
|
||||
* @see JComponent#updateUI
|
||||
*/
|
||||
public void updateUI() {
|
||||
// Update the UIs of the cell renderers, cell editors and header renderers.
|
||||
TableColumnModel cm = getColumnModel();
|
||||
for(int column = 0; column < cm.getColumnCount(); column++) {
|
||||
TableColumn aColumn = cm.getColumn(column);
|
||||
SwingUtilities.updateRendererOrEditorUI(aColumn.getCellRenderer());
|
||||
SwingUtilities.updateRendererOrEditorUI(aColumn.getCellEditor());
|
||||
SwingUtilities.updateRendererOrEditorUI(aColumn.getHeaderRenderer());
|
||||
if (updateInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the UIs of all the default renderers.
|
||||
Enumeration<?> defaultRenderers = defaultRenderersByColumnClass.elements();
|
||||
while (defaultRenderers.hasMoreElements()) {
|
||||
SwingUtilities.updateRendererOrEditorUI(defaultRenderers.nextElement());
|
||||
updateInProgress = true;
|
||||
|
||||
try {
|
||||
// Update the UIs of the cell renderers, cell editors and header renderers.
|
||||
TableColumnModel cm = getColumnModel();
|
||||
for(int column = 0; column < cm.getColumnCount(); column++) {
|
||||
TableColumn aColumn = cm.getColumn(column);
|
||||
SwingUtilities.updateRendererOrEditorUI(aColumn.getCellRenderer());
|
||||
SwingUtilities.updateRendererOrEditorUI(aColumn.getCellEditor());
|
||||
SwingUtilities.updateRendererOrEditorUI(aColumn.getHeaderRenderer());
|
||||
}
|
||||
|
||||
// Update the UIs of all the default renderers.
|
||||
Enumeration<?> defaultRenderers = defaultRenderersByColumnClass.elements();
|
||||
while (defaultRenderers.hasMoreElements()) {
|
||||
SwingUtilities.updateRendererOrEditorUI(defaultRenderers.nextElement());
|
||||
}
|
||||
|
||||
// Update the UIs of all the default editors.
|
||||
Enumeration<?> defaultEditors = defaultEditorsByColumnClass.elements();
|
||||
while (defaultEditors.hasMoreElements()) {
|
||||
SwingUtilities.updateRendererOrEditorUI(defaultEditors.nextElement());
|
||||
}
|
||||
|
||||
// Update the UI of the table header
|
||||
if (tableHeader != null && tableHeader.getParent() == null) {
|
||||
tableHeader.updateUI();
|
||||
}
|
||||
|
||||
// Update UI applied to parent ScrollPane
|
||||
configureEnclosingScrollPaneUI();
|
||||
|
||||
setUI((TableUI)UIManager.getUI(this));
|
||||
} finally {
|
||||
updateInProgress = false;
|
||||
}
|
||||
|
||||
// Update the UIs of all the default editors.
|
||||
Enumeration<?> defaultEditors = defaultEditorsByColumnClass.elements();
|
||||
while (defaultEditors.hasMoreElements()) {
|
||||
SwingUtilities.updateRendererOrEditorUI(defaultEditors.nextElement());
|
||||
}
|
||||
|
||||
// Update the UI of the table header
|
||||
if (tableHeader != null && tableHeader.getParent() == null) {
|
||||
tableHeader.updateUI();
|
||||
}
|
||||
|
||||
// Update UI applied to parent ScrollPane
|
||||
configureEnclosingScrollPaneUI();
|
||||
|
||||
setUI((TableUI)UIManager.getUI(this));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2016, 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
|
||||
@ -320,6 +320,11 @@ public class JTree extends JComponent implements Scrollable, Accessible
|
||||
*/
|
||||
private transient DropLocation dropLocation;
|
||||
|
||||
/**
|
||||
* Flag to indicate UI update is in progress
|
||||
*/
|
||||
private transient boolean updateInProgress;
|
||||
|
||||
/**
|
||||
* A subclass of <code>TransferHandler.DropLocation</code> representing
|
||||
* a drop location for a <code>JTree</code>.
|
||||
@ -713,10 +718,19 @@ public class JTree extends JComponent implements Scrollable, Accessible
|
||||
* @see JComponent#updateUI
|
||||
*/
|
||||
public void updateUI() {
|
||||
setUI((TreeUI)UIManager.getUI(this));
|
||||
if (!updateInProgress) {
|
||||
|
||||
SwingUtilities.updateRendererOrEditorUI(getCellRenderer());
|
||||
SwingUtilities.updateRendererOrEditorUI(getCellEditor());
|
||||
updateInProgress = true;
|
||||
|
||||
try {
|
||||
setUI((TreeUI)UIManager.getUI(this));
|
||||
|
||||
SwingUtilities.updateRendererOrEditorUI(getCellRenderer());
|
||||
SwingUtilities.updateRendererOrEditorUI(getCellEditor());
|
||||
} finally {
|
||||
updateInProgress = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2016, 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
|
||||
@ -118,6 +118,11 @@ public class JTableHeader extends JComponent implements TableColumnModelListener
|
||||
*/
|
||||
private TableCellRenderer defaultRenderer;
|
||||
|
||||
/**
|
||||
* Flag to indicate UI update is in progress
|
||||
*/
|
||||
private transient boolean updateInProgress;
|
||||
|
||||
//
|
||||
// Constructors
|
||||
//
|
||||
@ -475,11 +480,18 @@ public class JTableHeader extends JComponent implements TableColumnModelListener
|
||||
* @see JComponent#updateUI
|
||||
*/
|
||||
public void updateUI(){
|
||||
setUI((TableHeaderUI)UIManager.getUI(this));
|
||||
if (!updateInProgress) {
|
||||
updateInProgress = true;
|
||||
try {
|
||||
setUI((TableHeaderUI)UIManager.getUI(this));
|
||||
|
||||
TableCellRenderer renderer = getDefaultRenderer();
|
||||
if (renderer instanceof Component) {
|
||||
SwingUtilities.updateComponentTreeUI((Component)renderer);
|
||||
TableCellRenderer renderer = getDefaultRenderer();
|
||||
if (renderer instanceof Component) {
|
||||
SwingUtilities.updateComponentTreeUI((Component)renderer);
|
||||
}
|
||||
} finally {
|
||||
updateInProgress = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,10 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* java.desktop defines and exports the user interface, graphics
|
||||
* and imaging APIs of the Java SE platform.
|
||||
*/
|
||||
module java.desktop {
|
||||
requires public java.datatransfer;
|
||||
requires public java.xml;
|
||||
|
@ -187,17 +187,19 @@ public class OffScreenImageSource implements ImageProducer {
|
||||
sendPixels();
|
||||
theConsumer.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
|
||||
|
||||
try {
|
||||
theConsumer.imageComplete(ImageConsumer.STATICIMAGEDONE);
|
||||
} catch (RuntimeException e) {
|
||||
// We did not previously call this method here and
|
||||
// some image consumer filters were not prepared for it to be
|
||||
// called at this time. We allow them to have runtime issues
|
||||
// for this one call only without triggering the IMAGEERROR
|
||||
// condition below.
|
||||
e.printStackTrace();
|
||||
// If 'theconsumer' has not unregistered itself after previous call
|
||||
if (theConsumer != null) {
|
||||
try {
|
||||
theConsumer.imageComplete(ImageConsumer.STATICIMAGEDONE);
|
||||
} catch (RuntimeException e) {
|
||||
// We did not previously call this method here and
|
||||
// some image consumer filters were not prepared for it to be
|
||||
// called at this time. We allow them to have runtime issues
|
||||
// for this one call only without triggering the IMAGEERROR
|
||||
// condition below.
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
|
@ -28,6 +28,7 @@ package sun.font;
|
||||
import java.awt.Font;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import sun.java2d.loops.FontInfo;
|
||||
|
||||
/*
|
||||
@ -151,8 +152,8 @@ public final class GlyphList {
|
||||
* occur and if it did, it would just lead to some extra garbage being
|
||||
* created.
|
||||
*/
|
||||
private static GlyphList reusableGL = new GlyphList();
|
||||
private static boolean inUse;
|
||||
private static final GlyphList reusableGL = new GlyphList();
|
||||
private static final AtomicBoolean inUse = new AtomicBoolean();
|
||||
|
||||
|
||||
void ensureCapacity(int len) {
|
||||
@ -184,24 +185,10 @@ public final class GlyphList {
|
||||
// }
|
||||
|
||||
public static GlyphList getInstance() {
|
||||
/* The following heuristic is that if the reusable instance is
|
||||
* in use, it probably still will be in a micro-second, so avoid
|
||||
* synchronising on the class and just allocate a new instance.
|
||||
* The cost is one extra boolean test for the normal case, and some
|
||||
* small number of cases where we allocate an extra object when
|
||||
* in fact the reusable one would be freed very soon.
|
||||
*/
|
||||
if (inUse) {
|
||||
return new GlyphList();
|
||||
if (inUse.compareAndSet(false, true)) {
|
||||
return reusableGL;
|
||||
} else {
|
||||
synchronized(GlyphList.class) {
|
||||
if (inUse) {
|
||||
return new GlyphList();
|
||||
} else {
|
||||
inUse = true;
|
||||
return reusableGL;
|
||||
}
|
||||
}
|
||||
return new GlyphList();
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,17 +199,10 @@ public final class GlyphList {
|
||||
* will be discarded so the re-allocation overhead is high.
|
||||
*/
|
||||
// public static GlyphList getInstance(int sz) {
|
||||
// if (inUse) {
|
||||
// return new GlyphList(sz);
|
||||
// if (inUse.compareAndSet(false, true) {
|
||||
// return reusableGL;
|
||||
// } else {
|
||||
// synchronized(GlyphList.class) {
|
||||
// if (inUse) {
|
||||
// return new GlyphList();
|
||||
// } else {
|
||||
// inUse = true;
|
||||
// return reusableGL;
|
||||
// }
|
||||
// }
|
||||
// return new GlyphList(sz);
|
||||
// }
|
||||
// }
|
||||
|
||||
@ -423,7 +403,7 @@ public final class GlyphList {
|
||||
}
|
||||
usePositions = false;
|
||||
strikelist = null; // remove reference to the strike list
|
||||
inUse = false;
|
||||
inUse.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ import sun.print.SunPageSelection;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.net.URISyntaxException;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
/**
|
||||
* A class which implements a cross-platform print dialog.
|
||||
@ -932,12 +932,18 @@ public class ServiceDialog extends JDialog implements ActionListener {
|
||||
allowedToPrintToFile() : false;
|
||||
|
||||
// setup Destination (print-to-file) widgets
|
||||
if (psCurrent.isAttributeCategorySupported(dstCategory)) {
|
||||
dstSupported = true;
|
||||
}
|
||||
Destination dst = (Destination)asCurrent.get(dstCategory);
|
||||
if (dst != null) {
|
||||
dstSelected = true;
|
||||
try {
|
||||
dst.getURI().toURL();
|
||||
if (psCurrent.isAttributeValueSupported(dst, docFlavor,
|
||||
asCurrent)) {
|
||||
dstSupported = true;
|
||||
dstSelected = true;
|
||||
}
|
||||
} catch (MalformedURLException ex) {
|
||||
dstSupported = true;
|
||||
}
|
||||
}
|
||||
cbPrintToFile.setEnabled(dstSupported && dstAllowed);
|
||||
cbPrintToFile.setSelected(dstSelected && dstAllowed
|
||||
@ -1294,8 +1300,16 @@ public class ServiceDialog extends JDialog implements ActionListener {
|
||||
if (sc == null) {
|
||||
sc = SheetCollate.UNCOLLATED;
|
||||
}
|
||||
if (sc != null &&
|
||||
!psCurrent.isAttributeValueSupported(sc, docFlavor, asCurrent)) {
|
||||
scSupported = false;
|
||||
}
|
||||
} else {
|
||||
if (!psCurrent.isAttributeValueSupported(sc, docFlavor, asCurrent)) {
|
||||
scSupported = false;
|
||||
}
|
||||
}
|
||||
cbCollate.setSelected(sc == SheetCollate.COLLATED);
|
||||
cbCollate.setSelected(sc == SheetCollate.COLLATED && scSupported);
|
||||
updateCollateCB();
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
package sun.swing;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.*;
|
||||
import java.util.*;
|
||||
|
||||
@ -99,9 +100,7 @@ public abstract class CachedPainter {
|
||||
}
|
||||
}
|
||||
|
||||
private void paint0(Component c, Graphics g, int x,
|
||||
int y, int w, int h, Object... args) {
|
||||
Object key = getClass();
|
||||
private Image getImage(Object key, Component c, int w, int h, Object... args) {
|
||||
GraphicsConfiguration config = getGraphicsConfiguration(c);
|
||||
ImageCache cache = getCache(key);
|
||||
Image image = cache.getImage(key, config, w, h, args);
|
||||
@ -133,14 +132,40 @@ public abstract class CachedPainter {
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
// Render to the passed in Graphics
|
||||
paintImage(c, g, x, y, w, h, image, args);
|
||||
|
||||
// If we did this 3 times and the contents are still lost
|
||||
// assume we're painting to a VolatileImage that is bogus and
|
||||
// give up. Presumably we'll be called again to paint.
|
||||
} while ((image instanceof VolatileImage) &&
|
||||
((VolatileImage)image).contentsLost() && ++attempts < 3);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
private void paint0(Component c, Graphics g, int x,
|
||||
int y, int w, int h, Object... args) {
|
||||
Object key = getClass();
|
||||
GraphicsConfiguration config = getGraphicsConfiguration(c);
|
||||
ImageCache cache = getCache(key);
|
||||
Image image = cache.getImage(key, config, w, h, args);
|
||||
|
||||
if (image == null) {
|
||||
double sx = 1;
|
||||
double sy = 1;
|
||||
if (g instanceof Graphics2D) {
|
||||
AffineTransform tx = ((Graphics2D) g).getTransform();
|
||||
sx = tx.getScaleX();
|
||||
sy = tx.getScaleY();
|
||||
}
|
||||
image = new PainterMultiResolutionCachedImage(sx, sy, w, h);
|
||||
cache.setImage(key, config, w, h, args, image);
|
||||
}
|
||||
|
||||
if (image instanceof PainterMultiResolutionCachedImage) {
|
||||
((PainterMultiResolutionCachedImage) image).setParams(c, args);
|
||||
}
|
||||
|
||||
// Render to the passed in Graphics
|
||||
paintImage(c, g, x, y, w, h, image, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -210,4 +235,62 @@ public abstract class CachedPainter {
|
||||
}
|
||||
return c.getGraphicsConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
class PainterMultiResolutionCachedImage extends AbstractMultiResolutionImage {
|
||||
|
||||
private final double scaleX;
|
||||
private final double scaleY;
|
||||
private final int baseWidth;
|
||||
private final int baseHeight;
|
||||
private Component c;
|
||||
private Object[] args;
|
||||
|
||||
public PainterMultiResolutionCachedImage(double scaleX, double scaleY,
|
||||
int baseWidth, int baseHeight) {
|
||||
this.scaleX = scaleX;
|
||||
this.scaleY = scaleY;
|
||||
this.baseWidth = baseWidth;
|
||||
this.baseHeight = baseHeight;
|
||||
}
|
||||
|
||||
public void setParams(Component c, Object[] args) {
|
||||
this.c = c;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth(ImageObserver observer) {
|
||||
return baseWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight(ImageObserver observer) {
|
||||
return baseHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getResolutionVariant(double destWidth, double destHeight) {
|
||||
int w = (int) Math.ceil(destWidth);
|
||||
int h = (int) Math.ceil(destHeight);
|
||||
return getImage(this, c, w, h, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Image getBaseImage() {
|
||||
return getResolutionVariant(baseWidth, baseHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.List<Image> getResolutionVariants() {
|
||||
|
||||
if (scaleX == 1 && scaleY == 1) {
|
||||
return Arrays.asList(getResolutionVariant(baseWidth, baseHeight));
|
||||
}
|
||||
|
||||
return Arrays.asList(
|
||||
getResolutionVariant(baseWidth, baseHeight),
|
||||
getResolutionVariant(scaleX * baseWidth, scaleY * baseHeight)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -1748,8 +1748,8 @@ public class FilePane extends JPanel implements PropertyChangeListener {
|
||||
if (listSelectionModel != null) {
|
||||
listSelectionModel.clearSelection();
|
||||
if (listSelectionModel instanceof DefaultListSelectionModel) {
|
||||
((DefaultListSelectionModel)listSelectionModel).moveLeadSelectionIndex(0);
|
||||
listSelectionModel.setAnchorSelectionIndex(0);
|
||||
((DefaultListSelectionModel)listSelectionModel).moveLeadSelectionIndex(-1);
|
||||
listSelectionModel.setAnchorSelectionIndex(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2016, 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
|
||||
@ -29,6 +29,9 @@ import java.awt.*;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.InvocationEvent;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import sun.awt.IconInfo;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
@ -52,6 +55,8 @@ abstract class XDecoratedPeer extends XWindowPeer {
|
||||
XContentWindow content;
|
||||
Insets currentInsets;
|
||||
XFocusProxyWindow focusProxy;
|
||||
static final Map<Class<?>,Insets> lastKnownInsets =
|
||||
Collections.synchronizedMap(new HashMap<>());
|
||||
|
||||
XDecoratedPeer(Window target) {
|
||||
super(target);
|
||||
@ -74,6 +79,9 @@ abstract class XDecoratedPeer extends XWindowPeer {
|
||||
winAttr.initialFocus = true;
|
||||
|
||||
currentInsets = new Insets(0,0,0,0);
|
||||
if (XWM.getWMID() == XWM.UNITY_COMPIZ_WM) {
|
||||
currentInsets = lastKnownInsets.get(getClass());
|
||||
}
|
||||
applyGuessedInsets();
|
||||
|
||||
Rectangle bounds = (Rectangle)params.get(BOUNDS);
|
||||
@ -297,7 +305,25 @@ abstract class XDecoratedPeer extends XWindowPeer {
|
||||
if (ev.get_atom() == XWM.XA_KDE_NET_WM_FRAME_STRUT.getAtom()
|
||||
|| ev.get_atom() == XWM.XA_NET_FRAME_EXTENTS.getAtom())
|
||||
{
|
||||
getWMSetInsets(XAtom.get(ev.get_atom()));
|
||||
if (XWM.getWMID() != XWM.UNITY_COMPIZ_WM) {
|
||||
getWMSetInsets(XAtom.get(ev.get_atom()));
|
||||
} else {
|
||||
if(!isReparented()) {
|
||||
return;
|
||||
}
|
||||
wm_set_insets = null;
|
||||
Insets in = getWMSetInsets(XAtom.get(ev.get_atom()));
|
||||
if (isNull(in)) {
|
||||
return;
|
||||
}
|
||||
if (!isEmbedded() && !isTargetUndecorated()) {
|
||||
lastKnownInsets.put(getClass(), in);
|
||||
}
|
||||
if (!in.equals(dimensions.getInsets())) {
|
||||
handleCorrectInsets(in);
|
||||
}
|
||||
insets_corrected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -370,7 +396,7 @@ abstract class XDecoratedPeer extends XWindowPeer {
|
||||
}
|
||||
}
|
||||
|
||||
if (correctWM != null) {
|
||||
if (correctWM != null && XWM.getWMID() != XWM.UNITY_COMPIZ_WM) {
|
||||
handleCorrectInsets(correctWM);
|
||||
}
|
||||
}
|
||||
@ -664,6 +690,9 @@ abstract class XDecoratedPeer extends XWindowPeer {
|
||||
|
||||
boolean no_reparent_artifacts = false;
|
||||
public void handleConfigureNotifyEvent(XEvent xev) {
|
||||
if (XWM.getWMID() == XWM.UNITY_COMPIZ_WM && !insets_corrected) {
|
||||
return;
|
||||
}
|
||||
assert (SunToolkit.isAWTLockHeldByCurrentThread());
|
||||
XConfigureEvent xe = xev.get_xconfigure();
|
||||
if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
@ -1010,7 +1039,22 @@ abstract class XDecoratedPeer extends XWindowPeer {
|
||||
if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
focusLog.fine("WM_TAKE_FOCUS on {0}", this);
|
||||
}
|
||||
requestWindowFocus(cl.get_data(1), true);
|
||||
|
||||
if (XWM.getWMID() == XWM.UNITY_COMPIZ_WM) {
|
||||
// JDK-8159460
|
||||
Window focusedWindow = XKeyboardFocusManagerPeer.getInstance()
|
||||
.getCurrentFocusedWindow();
|
||||
Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow);
|
||||
if (activeWindow != target) {
|
||||
requestWindowFocus(cl.get_data(1), true);
|
||||
} else {
|
||||
WindowEvent we = new WindowEvent(focusedWindow,
|
||||
WindowEvent.WINDOW_GAINED_FOCUS);
|
||||
sendEvent(we);
|
||||
}
|
||||
} else {
|
||||
requestWindowFocus(cl.get_data(1), true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,8 +35,16 @@ import sun.awt.X11GraphicsEnvironment;
|
||||
|
||||
class XRobotPeer implements RobotPeer {
|
||||
|
||||
private static volatile boolean isGtkSupported;
|
||||
static final boolean tryGtk;
|
||||
static {
|
||||
loadNativeLibraries();
|
||||
tryGtk = Boolean.getBoolean("awt.robot.gtk");
|
||||
}
|
||||
|
||||
private static boolean isGtkSupported = false;
|
||||
private static volatile boolean useGtk;
|
||||
private X11GraphicsConfig xgc = null;
|
||||
|
||||
/*
|
||||
* native implementation uses some static shared data (pipes, processes)
|
||||
* so use a class lock to synchronize native method calls
|
||||
@ -49,13 +57,14 @@ class XRobotPeer implements RobotPeer {
|
||||
setup(tk.getNumberOfButtons(),
|
||||
AWTAccessor.getInputEventAccessor().getButtonDownMasks());
|
||||
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
if (!isGtkSupported) {
|
||||
if (toolkit instanceof UNIXToolkit
|
||||
&& ((UNIXToolkit) toolkit).loadGTK()) {
|
||||
boolean isGtkSupported = false;
|
||||
if (tryGtk) {
|
||||
if (tk instanceof UNIXToolkit && ((UNIXToolkit) tk).loadGTK()) {
|
||||
isGtkSupported = true;
|
||||
}
|
||||
}
|
||||
|
||||
useGtk = (tryGtk && isGtkSupported);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -104,7 +113,7 @@ class XRobotPeer implements RobotPeer {
|
||||
public int getRGBPixel(int x, int y) {
|
||||
int pixelArray[] = new int[1];
|
||||
getRGBPixelsImpl(xgc, x, y, 1, 1, xgc.getScale(), pixelArray,
|
||||
isGtkSupported);
|
||||
useGtk);
|
||||
return pixelArray[0];
|
||||
}
|
||||
|
||||
@ -112,11 +121,12 @@ class XRobotPeer implements RobotPeer {
|
||||
public int [] getRGBPixels(Rectangle bounds) {
|
||||
int pixelArray[] = new int[bounds.width*bounds.height];
|
||||
getRGBPixelsImpl(xgc, bounds.x, bounds.y, bounds.width, bounds.height,
|
||||
xgc.getScale(), pixelArray, isGtkSupported);
|
||||
xgc.getScale(), pixelArray, useGtk);
|
||||
return pixelArray;
|
||||
}
|
||||
|
||||
private static synchronized native void setup(int numberOfButtons, int[] buttonDownMasks);
|
||||
private static native void loadNativeLibraries();
|
||||
|
||||
private static synchronized native void mouseMoveImpl(X11GraphicsConfig xgc, int x, int y);
|
||||
private static synchronized native void mousePressImpl(int buttons);
|
||||
|
@ -32,6 +32,7 @@ import java.awt.event.ActionEvent;
|
||||
|
||||
import sun.awt.UNIXToolkit;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
final class XTaskbarPeer implements TaskbarPeer {
|
||||
@ -40,6 +41,14 @@ final class XTaskbarPeer implements TaskbarPeer {
|
||||
private static boolean initExecuted = false;
|
||||
|
||||
private PopupMenu menu = null;
|
||||
private static boolean isUnity;
|
||||
|
||||
static {
|
||||
String de = AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) ()
|
||||
-> System.getenv("XDG_CURRENT_DESKTOP"));
|
||||
isUnity = de != null && de.equals("Unity");
|
||||
}
|
||||
|
||||
private static void initWithLock() {
|
||||
XToolkit.awtLock();
|
||||
@ -68,6 +77,9 @@ final class XTaskbarPeer implements TaskbarPeer {
|
||||
}
|
||||
|
||||
static boolean isTaskbarSupported() {
|
||||
if (!isUnity) {
|
||||
return false;
|
||||
}
|
||||
initWithLock();
|
||||
return nativeLibraryLoaded;
|
||||
}
|
||||
@ -107,6 +119,8 @@ final class XTaskbarPeer implements TaskbarPeer {
|
||||
val = Long.parseLong(badge);
|
||||
visible = true;
|
||||
} catch (NumberFormatException e) {
|
||||
throw new UnsupportedOperationException("The " + Feature.ICON_BADGE_TEXT
|
||||
+ " feature is not supported on the current platform!");
|
||||
}
|
||||
}
|
||||
setBadge(val, visible);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2016, 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
|
||||
@ -104,7 +104,8 @@ final class XWM
|
||||
COMPIZ_WM = 12,
|
||||
LG3D_WM = 13,
|
||||
CWM_WM = 14,
|
||||
MUTTER_WM = 15;
|
||||
MUTTER_WM = 15,
|
||||
UNITY_COMPIZ_WM = 16;
|
||||
public String toString() {
|
||||
switch (WMID) {
|
||||
case NO_WM:
|
||||
@ -129,6 +130,8 @@ final class XWM
|
||||
return "Metacity";
|
||||
case COMPIZ_WM:
|
||||
return "Compiz";
|
||||
case UNITY_COMPIZ_WM:
|
||||
return "Unity Compiz";
|
||||
case LG3D_WM:
|
||||
return "LookingGlass";
|
||||
case CWM_WM:
|
||||
@ -572,6 +575,10 @@ final class XWM
|
||||
return isNetWMName("compiz");
|
||||
}
|
||||
|
||||
static boolean isUnityCompiz() {
|
||||
return isNetWMName("Compiz");
|
||||
}
|
||||
|
||||
static boolean isLookingGlass() {
|
||||
return isNetWMName("LG3D");
|
||||
}
|
||||
@ -790,6 +797,8 @@ final class XWM
|
||||
awt_wmgr = CWM_WM;
|
||||
} else if (doIsIceWM && isIceWM()) {
|
||||
awt_wmgr = XWM.ICE_WM;
|
||||
} else if (isUnityCompiz()) {
|
||||
awt_wmgr = XWM.UNITY_COMPIZ_WM;
|
||||
}
|
||||
/*
|
||||
* We don't check for legacy WM when we already know that WM
|
||||
@ -1351,6 +1360,9 @@ final class XWM
|
||||
case LG3D_WM:
|
||||
res = zeroInsets;
|
||||
break;
|
||||
case UNITY_COMPIZ_WM:
|
||||
res = new Insets(28, 1, 1, 1);
|
||||
break;
|
||||
case MOTIF_WM:
|
||||
case OPENLOOK_WM:
|
||||
default:
|
||||
|
@ -777,6 +777,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
|
||||
case XWM.METACITY_WM:
|
||||
case XWM.MUTTER_WM:
|
||||
case XWM.SAWFISH_WM:
|
||||
case XWM.UNITY_COMPIZ_WM:
|
||||
{
|
||||
Point xlocation = queryXLocation();
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2016, 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
|
||||
@ -281,7 +281,7 @@ public final class X11GraphicsDevice extends GraphicsDevice
|
||||
int width, int height,
|
||||
int displayMode);
|
||||
private static native void resetNativeData(int screen);
|
||||
private static native int getNativeScaleFactor(int screen);
|
||||
private static native double getNativeScaleFactor(int screen);
|
||||
|
||||
/**
|
||||
* Returns true only if:
|
||||
@ -516,6 +516,11 @@ public final class X11GraphicsDevice extends GraphicsDevice
|
||||
return scale;
|
||||
}
|
||||
|
||||
public int getNativeScale() {
|
||||
isXrandrExtensionSupported();
|
||||
return (int)Math.round(getNativeScaleFactor(screen));
|
||||
}
|
||||
|
||||
private int initScaleFactor() {
|
||||
|
||||
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
|
||||
@ -525,8 +530,7 @@ public final class X11GraphicsDevice extends GraphicsDevice
|
||||
if (debugScale >= 1) {
|
||||
return (int) debugScale;
|
||||
}
|
||||
|
||||
int nativeScale = getNativeScaleFactor(screen);
|
||||
int nativeScale = getNativeScale();
|
||||
return nativeScale >= 1 ? nativeScale : 1;
|
||||
}
|
||||
|
||||
|
@ -22,23 +22,171 @@
|
||||
*/
|
||||
|
||||
#include "systemScale.h"
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "jvm_md.h"
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int getNativeScaleFactor() {
|
||||
typedef void* g_settings_schema_source_get_default();
|
||||
typedef void* g_settings_schema_source_ref(void *);
|
||||
typedef void g_settings_schema_source_unref(void *);
|
||||
typedef void* g_settings_schema_source_lookup(void *, char *, int);
|
||||
typedef int g_settings_schema_has_key(void *, char *);
|
||||
typedef void* g_settings_new_full(void *, void *, char *);
|
||||
typedef void* g_settings_get_value(void *, char *);
|
||||
typedef int g_variant_is_of_type(void *, char *);
|
||||
typedef unsigned long g_variant_n_children(void *);
|
||||
typedef void* g_variant_get_child_value(void *, unsigned long);
|
||||
typedef void g_variant_unref(void *);
|
||||
typedef char* g_variant_get_string(void *, unsigned long *);
|
||||
typedef int g_variant_get_int32(void *);
|
||||
typedef double g_variant_get_double(void *);
|
||||
|
||||
static int scale = -2.0;
|
||||
static g_settings_schema_has_key* fp_g_settings_schema_has_key;
|
||||
static g_settings_new_full* fp_g_settings_new_full;
|
||||
static g_settings_get_value* fp_g_settings_get_value;
|
||||
static g_variant_is_of_type* fp_g_variant_is_of_type;
|
||||
static g_variant_n_children* fp_g_variant_n_children;
|
||||
static g_variant_get_child_value* fp_g_variant_get_child_value;
|
||||
static g_variant_get_string* fp_g_variant_get_string;
|
||||
static g_variant_get_int32* fp_g_variant_get_int32;
|
||||
static g_variant_get_double* fp_g_variant_get_double;
|
||||
static g_variant_unref* fp_g_variant_unref;
|
||||
|
||||
if (scale == -2) {
|
||||
scale = getScale("J2D_UISCALE");
|
||||
static void* get_schema_value(char *name, char *key) {
|
||||
static void *lib_handle;
|
||||
static int initialized = 0;
|
||||
static void * default_schema;
|
||||
static g_settings_schema_source_lookup* schema_lookup;
|
||||
void *schema = NULL, *fp = NULL;
|
||||
if (!initialized) {
|
||||
initialized = 1;
|
||||
lib_handle = dlopen(JNI_LIB_NAME("gio-2.0"), RTLD_GLOBAL | RTLD_LAZY);
|
||||
if (!lib_handle) {
|
||||
CHECK_NULL_RETURN(lib_handle =
|
||||
dlopen(VERSIONED_JNI_LIB_NAME("gio-2.0", "0"),
|
||||
RTLD_GLOBAL | RTLD_LAZY), NULL);
|
||||
}
|
||||
CHECK_NULL_RETURN(fp_g_settings_schema_has_key =
|
||||
(g_settings_schema_has_key*)
|
||||
dlsym(lib_handle, "g_settings_schema_has_key"), NULL);
|
||||
CHECK_NULL_RETURN(fp_g_settings_new_full =
|
||||
(g_settings_new_full*)
|
||||
dlsym(lib_handle, "g_settings_new_full"), NULL);
|
||||
CHECK_NULL_RETURN(fp_g_settings_get_value =
|
||||
(g_settings_get_value*)
|
||||
dlsym(lib_handle, "g_settings_get_value"), NULL);
|
||||
CHECK_NULL_RETURN(fp_g_variant_is_of_type =
|
||||
(g_variant_is_of_type*)
|
||||
dlsym(lib_handle, "g_variant_is_of_type"), NULL);
|
||||
CHECK_NULL_RETURN(fp_g_variant_n_children =
|
||||
(g_variant_n_children*)
|
||||
dlsym(lib_handle, "g_variant_n_children"), NULL);
|
||||
CHECK_NULL_RETURN(fp_g_variant_get_child_value =
|
||||
(g_variant_get_child_value*)
|
||||
dlsym(lib_handle, "g_variant_get_child_value"), NULL);
|
||||
CHECK_NULL_RETURN(fp_g_variant_get_string =
|
||||
(g_variant_get_string*)
|
||||
dlsym(lib_handle, "g_variant_get_string"), NULL);
|
||||
CHECK_NULL_RETURN(fp_g_variant_get_int32 =
|
||||
(g_variant_get_int32*)
|
||||
dlsym(lib_handle, "g_variant_get_int32"), NULL);
|
||||
CHECK_NULL_RETURN(fp_g_variant_get_double =
|
||||
(g_variant_get_double*)
|
||||
dlsym(lib_handle, "g_variant_get_double"), NULL);
|
||||
CHECK_NULL_RETURN(fp_g_variant_unref =
|
||||
(g_variant_unref*)
|
||||
dlsym(lib_handle, "g_variant_unref"), NULL);
|
||||
|
||||
fp = dlsym(lib_handle, "g_settings_schema_source_get_default");
|
||||
if (fp) {
|
||||
default_schema = ((g_settings_schema_source_get_default*)fp)();
|
||||
}
|
||||
if (default_schema) {
|
||||
fp = dlsym(lib_handle, "g_settings_schema_source_ref");
|
||||
if (fp) {
|
||||
((g_settings_schema_source_ref*)fp)(default_schema);
|
||||
}
|
||||
}
|
||||
schema_lookup = (g_settings_schema_source_lookup*)
|
||||
dlsym(lib_handle, "g_settings_schema_source_lookup");
|
||||
}
|
||||
|
||||
if (scale >= 1) {
|
||||
return (int) scale;
|
||||
if (!default_schema || !schema_lookup) {
|
||||
return NULL;
|
||||
}
|
||||
return getScale("GDK_SCALE");
|
||||
|
||||
schema = schema_lookup(default_schema, name, 1);
|
||||
if (schema) {
|
||||
if (fp_g_settings_schema_has_key(schema, key)) {
|
||||
void *settings = fp_g_settings_new_full(schema, NULL, NULL);
|
||||
if (settings) {
|
||||
return fp_g_settings_get_value(settings, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int getScale(const char *name) {
|
||||
|
||||
static double getDesktopScale(char *output_name) {
|
||||
double result = -1;
|
||||
if(output_name) {
|
||||
void *value = get_schema_value("com.ubuntu.user-interface",
|
||||
"scale-factor");
|
||||
if (value) {
|
||||
if(fp_g_variant_is_of_type(value, "a{si}")) {
|
||||
int num = fp_g_variant_n_children(value);
|
||||
int i = 0;
|
||||
while (i < num) {
|
||||
void *entry = fp_g_variant_get_child_value(value, i++);
|
||||
if (entry) {
|
||||
void *screen = fp_g_variant_get_child_value(entry, 0);
|
||||
void *scale = fp_g_variant_get_child_value(entry, 1);
|
||||
if (screen && scale) {
|
||||
char *name = fp_g_variant_get_string(screen, NULL);
|
||||
if (name && strcmp(name, output_name)) {
|
||||
result = fp_g_variant_get_int32(scale) / 8.;
|
||||
}
|
||||
fp_g_variant_unref(screen);
|
||||
fp_g_variant_unref(scale);
|
||||
}
|
||||
fp_g_variant_unref(entry);
|
||||
}
|
||||
if (result > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fp_g_variant_unref(value);
|
||||
}
|
||||
if (result > 0) {
|
||||
value = get_schema_value("com.canonical.Unity.Interface",
|
||||
"text-scale-factor");
|
||||
if (value && fp_g_variant_is_of_type(value, "d")) {
|
||||
result *= fp_g_variant_get_double(value);
|
||||
fp_g_variant_unref(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result <= 0) {
|
||||
void *value = get_schema_value("org.gnome.desktop.interface",
|
||||
"text-scaling-factor");
|
||||
if (value && fp_g_variant_is_of_type(value, "d")) {
|
||||
result = fp_g_variant_get_double(value);
|
||||
fp_g_variant_unref(value);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
static int getScale(const char *name) {
|
||||
char *uiScale = getenv(name);
|
||||
if (uiScale != NULL) {
|
||||
double scale = strtod(uiScale, NULL);
|
||||
@ -50,3 +198,26 @@ int getScale(const char *name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
double getNativeScaleFactor(char *output_name) {
|
||||
static int scale = -2.0;
|
||||
double native_scale = 0;
|
||||
int gdk_scale = 0;
|
||||
|
||||
if (scale == -2) {
|
||||
scale = getScale("J2D_UISCALE");
|
||||
}
|
||||
|
||||
if (scale > 0) {
|
||||
return scale;
|
||||
}
|
||||
|
||||
native_scale = getDesktopScale(output_name);
|
||||
|
||||
if (native_scale <= 0) {
|
||||
native_scale = 1;
|
||||
}
|
||||
|
||||
gdk_scale = getScale("GDK_SCALE");
|
||||
|
||||
return gdk_scale > 0 ? native_scale * gdk_scale : native_scale;
|
||||
}
|
||||
|
@ -26,8 +26,7 @@
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int getNativeScaleFactor();
|
||||
int getScale(const char *uiScale);
|
||||
double getNativeScaleFactor();
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -2141,15 +2141,50 @@ Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive
|
||||
* End DisplayMode/FullScreen support
|
||||
*/
|
||||
|
||||
static char *get_output_screen_name(JNIEnv *env, int screen) {
|
||||
if (!awt_XRRGetScreenResources || !awt_XRRGetOutputInfo) {
|
||||
return NULL;
|
||||
}
|
||||
char *name = NULL;
|
||||
AWT_LOCK();
|
||||
int scr = 0, out = 0;
|
||||
if (usingXinerama && XScreenCount(awt_display) > 0) {
|
||||
out = screen;
|
||||
} else {
|
||||
scr = screen;
|
||||
}
|
||||
|
||||
XRRScreenResources *res = awt_XRRGetScreenResources(awt_display,
|
||||
RootWindow(awt_display, scr));
|
||||
if (res) {
|
||||
if (res->noutput > out) {
|
||||
XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display,
|
||||
res, res->outputs[out]);
|
||||
if (output_info) {
|
||||
if (output_info->name) {
|
||||
name = strdup(output_info->name);
|
||||
}
|
||||
awt_XRRFreeOutputInfo(output_info);
|
||||
}
|
||||
}
|
||||
awt_XRRFreeScreenResources(res);
|
||||
}
|
||||
AWT_UNLOCK();
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_awt_X11GraphicsDevice
|
||||
* Method: getNativeScaleFactor
|
||||
* Signature: (I)I
|
||||
* Signature: (I)D
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
JNIEXPORT jdouble JNICALL
|
||||
Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor
|
||||
(JNIEnv *env, jobject this, jint screen) {
|
||||
|
||||
return getNativeScaleFactor();
|
||||
char *name = get_output_screen_name(env, screen);
|
||||
double scale = getNativeScaleFactor(name);
|
||||
if (name) {
|
||||
free(name);
|
||||
}
|
||||
return scale;
|
||||
}
|
||||
|
@ -27,6 +27,9 @@
|
||||
#error This file should not be included in headless library
|
||||
#endif
|
||||
|
||||
#include "jvm_md.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "awt_p.h"
|
||||
#include "awt_GraphicsEnv.h"
|
||||
#define XK_MISCELLANY
|
||||
@ -50,11 +53,46 @@
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
static Bool (*compositeQueryExtension) (Display*, int*, int*);
|
||||
static Status (*compositeQueryVersion) (Display*, int*, int*);
|
||||
static Window (*compositeGetOverlayWindow) (Display *, Window);
|
||||
|
||||
extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
|
||||
|
||||
static jint * masks;
|
||||
static jint num_buttons;
|
||||
|
||||
static void *xCompositeHandle;
|
||||
|
||||
static const char* XCOMPOSITE = JNI_LIB_NAME("Xcomposite");
|
||||
static const char* XCOMPOSITE_VERSIONED = VERSIONED_JNI_LIB_NAME("Xcomposite", "1");
|
||||
|
||||
static Bool checkXCompositeFunctions(void) {
|
||||
return (compositeQueryExtension != NULL &&
|
||||
compositeQueryVersion != NULL &&
|
||||
compositeGetOverlayWindow != NULL);
|
||||
}
|
||||
|
||||
static void initXCompositeFunctions(void) {
|
||||
|
||||
if (xCompositeHandle == NULL) {
|
||||
xCompositeHandle = dlopen(XCOMPOSITE, RTLD_LAZY | RTLD_GLOBAL);
|
||||
if (xCompositeHandle == NULL) {
|
||||
xCompositeHandle = dlopen(XCOMPOSITE_VERSIONED, RTLD_LAZY | RTLD_GLOBAL);
|
||||
}
|
||||
}
|
||||
//*(void **)(&asyncGetCallTraceFunction)
|
||||
if (xCompositeHandle != NULL) {
|
||||
*(void **)(&compositeQueryExtension) = dlsym(xCompositeHandle, "XCompositeQueryExtension");
|
||||
*(void **)(&compositeQueryVersion) = dlsym(xCompositeHandle, "XCompositeQueryVersion");
|
||||
*(void **)(&compositeGetOverlayWindow) = dlsym(xCompositeHandle, "XCompositeGetOverlayWindow");
|
||||
}
|
||||
|
||||
if (xCompositeHandle && !checkXCompositeFunctions()) {
|
||||
dlclose(xCompositeHandle);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t isXTestAvailable() {
|
||||
int32_t major_opcode, first_event, first_error;
|
||||
int32_t event_basep, error_basep, majorp, minorp;
|
||||
@ -89,6 +127,35 @@ static int32_t isXTestAvailable() {
|
||||
return isXTestAvailable;
|
||||
}
|
||||
|
||||
static Bool hasXCompositeOverlayExtension(Display *display) {
|
||||
|
||||
int xoverlay = False;
|
||||
int eventBase, errorBase;
|
||||
if (checkXCompositeFunctions() &&
|
||||
compositeQueryExtension(display, &eventBase, &errorBase))
|
||||
{
|
||||
int major = 0;
|
||||
int minor = 0;
|
||||
|
||||
compositeQueryVersion(display, &major, &minor);
|
||||
if (major > 0 || minor >= 3) {
|
||||
xoverlay = True;
|
||||
}
|
||||
}
|
||||
|
||||
return xoverlay;
|
||||
}
|
||||
|
||||
static jboolean isXCompositeDisplay(Display *display, int screenNumber) {
|
||||
|
||||
char NET_WM_CM_Sn[25];
|
||||
snprintf(NET_WM_CM_Sn, sizeof(NET_WM_CM_Sn), "_NET_WM_CM_S%d\0", screenNumber);
|
||||
|
||||
Atom managerSelection = XInternAtom(display, NET_WM_CM_Sn, 0);
|
||||
Window owner = XGetSelectionOwner(display, managerSelection);
|
||||
|
||||
return owner != 0;
|
||||
}
|
||||
|
||||
static XImage *getWindowImage(Display * display, Window window,
|
||||
int32_t x, int32_t y,
|
||||
@ -211,7 +278,7 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
|
||||
jint jheight,
|
||||
jint scale,
|
||||
jintArray pixelArray,
|
||||
jboolean isGtkSupported) {
|
||||
jboolean useGtk) {
|
||||
XImage *image;
|
||||
jint *ary; /* Array of jints for sending pixel values back
|
||||
* to parent process.
|
||||
@ -238,6 +305,14 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
|
||||
|
||||
rootWindow = XRootWindow(awt_display, adata->awt_visInfo.screen);
|
||||
|
||||
if (!useGtk) {
|
||||
if (hasXCompositeOverlayExtension(awt_display) &&
|
||||
isXCompositeDisplay(awt_display, adata->awt_visInfo.screen))
|
||||
{
|
||||
rootWindow = compositeGetOverlayWindow(awt_display, rootWindow);
|
||||
}
|
||||
}
|
||||
|
||||
if (!XGetWindowAttributes(awt_display, rootWindow, &attr)
|
||||
|| sx + swidth <= attr.x
|
||||
|| attr.x + attr.width <= sx
|
||||
@ -262,7 +337,7 @@ Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
|
||||
|
||||
int index;
|
||||
|
||||
if (isGtkSupported) {
|
||||
if (useGtk) {
|
||||
gtk->gdk_threads_enter();
|
||||
gtk_failed = gtk->get_drawable_data(env, pixelArray, x, y, width,
|
||||
height, jwidth, dx, dy, scale);
|
||||
@ -454,3 +529,8 @@ Java_sun_awt_X11_XRobotPeer_mouseWheelImpl (JNIEnv *env,
|
||||
|
||||
AWT_UNLOCK();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_X11_XRobotPeer_loadNativeLibraries (JNIEnv *env, jclass cls) {
|
||||
initXCompositeFunctions();
|
||||
}
|
||||
|
@ -1586,13 +1586,17 @@ static void gtk3_paint_expander(WidgetType widget_type, GtkStateType state_type,
|
||||
fp_gtk_style_context_save (context);
|
||||
|
||||
GtkStateFlags flags = get_gtk_flags(state_type);
|
||||
if (expander_style == GTK_EXPANDER_EXPANDED) {
|
||||
flags |= GTK_STATE_FLAG_ACTIVE;
|
||||
}
|
||||
|
||||
fp_gtk_style_context_set_state(context, flags);
|
||||
|
||||
if (detail != 0) {
|
||||
transform_detail_string(detail, context);
|
||||
}
|
||||
|
||||
fp_gtk_render_expander (context, cr, x, y, width, height);
|
||||
fp_gtk_render_expander (context, cr, x + 2, y + 2, width - 4, height - 4);
|
||||
|
||||
fp_gtk_style_context_restore (context);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
* 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 thats
|
||||
* 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
|
||||
|
@ -55,6 +55,7 @@ import sun.awt.event.IgnorePaintEvent;
|
||||
|
||||
import java.awt.dnd.DropTarget;
|
||||
import java.awt.dnd.peer.DropTargetPeer;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import sun.awt.AWTAccessor;
|
||||
|
||||
import sun.util.logging.PlatformLogger;
|
||||
@ -1128,6 +1129,12 @@ public abstract class WComponentPeer extends WObjectPeer
|
||||
}
|
||||
|
||||
if (shape != null) {
|
||||
AffineTransform tx = winGraphicsConfig.getDefaultTransform();
|
||||
double scaleX = tx.getScaleX();
|
||||
double scaleY = tx.getScaleY();
|
||||
if (scaleX != 1 || scaleY != 1) {
|
||||
shape = shape.getScaledRegion(scaleX, scaleY);
|
||||
}
|
||||
setRectangularShape(shape.getLoX(), shape.getLoY(), shape.getHiX(), shape.getHiY(),
|
||||
(shape.isRectangular() ? null : shape));
|
||||
} else {
|
||||
|
@ -473,8 +473,14 @@ Java_sun_awt_windows_WGlobalCursorManager_getCursorPos(JNIEnv *env,
|
||||
|
||||
POINT p;
|
||||
::GetCursorPos(&p);
|
||||
env->SetIntField(point, AwtCursor::pointXID, (jint)p.x);
|
||||
env->SetIntField(point, AwtCursor::pointYID, (jint)p.y);
|
||||
HMONITOR monitor = MonitorFromPoint(p, MONITOR_DEFAULTTOPRIMARY);
|
||||
int screen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(monitor);
|
||||
Devices::InstanceAccess devices;
|
||||
AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
|
||||
int x = (device == NULL) ? p.x : device->ScaleDownX(p.x);
|
||||
int y = (device == NULL) ? p.y : device->ScaleDownY(p.y);
|
||||
env->SetIntField(point, AwtCursor::pointXID, x);
|
||||
env->SetIntField(point, AwtCursor::pointYID, y);
|
||||
|
||||
CATCH_BAD_ALLOC;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2016, 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
|
||||
@ -32,6 +32,20 @@
|
||||
|
||||
#define BSIZE (max(512, MAX_PATH+1))
|
||||
|
||||
/* Typically all local references held by a JNI function are automatically
|
||||
* released by JVM when the function returns. However, there is a limit to the
|
||||
* number of local references that can remain active. If the local references
|
||||
* continue to grow, it could result in out of memory error. Henceforth, we
|
||||
* invoke DeleteLocalRef on objects that are no longer needed for execution in
|
||||
* the JNI function.
|
||||
*/
|
||||
#define DeleteLocalReference(env, jniRef) \
|
||||
do { \
|
||||
if (jniRef != NULL) { \
|
||||
(*env)->DeleteLocalRef(env, jniRef); \
|
||||
jniRef = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_sun_awt_Win32FontManager_getFontPath(JNIEnv *env, jobject thiz, jboolean noType1)
|
||||
{
|
||||
@ -88,81 +102,9 @@ typedef struct GdiFontMapInfo {
|
||||
jobject locale;
|
||||
} GdiFontMapInfo;
|
||||
|
||||
/* IS_NT means NT or later OSes which support Unicode.
|
||||
* We have to painfully deal with the ASCII and non-ASCII case we
|
||||
* we really want to get the font names as unicode wherever possible.
|
||||
* UNICODE_OS is 0 to mean uninitialised, 1 to mean not a unicode OS,
|
||||
* 2 to mean a unicode OS.
|
||||
*/
|
||||
|
||||
#define UC_UNKNOWN 0
|
||||
#define UC_NO 1
|
||||
#define UC_YES 2
|
||||
static int UNICODE_OS = UC_UNKNOWN;
|
||||
static int GetOSVersion () {
|
||||
OSVERSIONINFO vinfo;
|
||||
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
|
||||
GetVersionEx(&vinfo);
|
||||
if ((int)vinfo.dwMajorVersion > 4) {
|
||||
UNICODE_OS = UC_YES;
|
||||
} else if ((int)vinfo.dwMajorVersion < 4) {
|
||||
UNICODE_OS = UC_NO;
|
||||
} else {
|
||||
if ((int)vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
|
||||
UNICODE_OS = UC_NO;
|
||||
} else {
|
||||
UNICODE_OS = UC_YES;
|
||||
}
|
||||
}
|
||||
return UNICODE_OS;
|
||||
}
|
||||
|
||||
#define IS_NT ((UNICODE_OS == UC_UNKNOWN) \
|
||||
? (GetOSVersion() == UC_YES) : (UNICODE_OS == UC_YES))
|
||||
|
||||
/* NT is W2K & XP. WIN is Win9x */
|
||||
/* Registry entry for fonts */
|
||||
static const char FONTKEY_NT[] =
|
||||
"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
|
||||
static const char FONTKEY_WIN[] =
|
||||
"Software\\Microsoft\\Windows\\CurrentVersion\\Fonts";
|
||||
|
||||
/* Callback for call to EnumFontFamiliesEx in the EnumFamilyNames function.
|
||||
* Expects to be called once for each face name in the family specified
|
||||
* in the call. We extract the full name for the font which is expected
|
||||
* to be in the "system encoding" and create canonical and lower case
|
||||
* Java strings for the name which are added to the maps. The lower case
|
||||
* name is used as key to the family name value in the font to family map,
|
||||
* the canonical name is one of the"list" of members of the family.
|
||||
*/
|
||||
static int CALLBACK EnumFontFacesInFamilyProcA(
|
||||
ENUMLOGFONTEXA *lpelfe,
|
||||
NEWTEXTMETRICEX *lpntme,
|
||||
int FontType,
|
||||
LPARAM lParam )
|
||||
{
|
||||
GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;
|
||||
JNIEnv *env = fmi->env;
|
||||
jstring fullname, fullnameLC;
|
||||
|
||||
/* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
|
||||
if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* printf("FULL=%s\n",lpelfe->elfFullName);fflush(stdout); */
|
||||
|
||||
fullname = JNU_NewStringPlatform(env, lpelfe->elfFullName);
|
||||
if (fullname == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
return 1;
|
||||
}
|
||||
fullnameLC = (*env)->CallObjectMethod(env, fullname,
|
||||
fmi->toLowerCaseMID, fmi->locale);
|
||||
(*env)->CallBooleanMethod(env, fmi->list, fmi->addMID, fullname);
|
||||
(*env)->CallObjectMethod(env, fmi->fontToFamilyMap,
|
||||
fmi->putMID, fullnameLC, fmi->family);
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct CheckFamilyInfo {
|
||||
wchar_t *family;
|
||||
@ -219,6 +161,14 @@ static int DifferentFamily(wchar_t *family, wchar_t* fullName) {
|
||||
return info.isDifferent;
|
||||
}
|
||||
|
||||
/* Callback for call to EnumFontFamiliesEx in the EnumFamilyNames function.
|
||||
* Expects to be called once for each face name in the family specified
|
||||
* in the call. We extract the full name for the font which is expected
|
||||
* to be in the "system encoding" and create canonical and lower case
|
||||
* Java strings for the name which are added to the maps. The lower case
|
||||
* name is used as key to the family name value in the font to family map,
|
||||
* the canonical name is one of the"list" of members of the family.
|
||||
*/
|
||||
static int CALLBACK EnumFontFacesInFamilyProcW(
|
||||
ENUMLOGFONTEXW *lpelfe,
|
||||
NEWTEXTMETRICEX *lpntme,
|
||||
@ -229,6 +179,19 @@ static int CALLBACK EnumFontFacesInFamilyProcW(
|
||||
JNIEnv *env = fmi->env;
|
||||
jstring fullname, fullnameLC;
|
||||
|
||||
/* Exceptions indicate critical errors such that program cannot continue
|
||||
* with further execution. Henceforth, the function returns immediately
|
||||
* on pending exceptions. In these situations, the function also returns
|
||||
* 0 indicating windows API to stop further enumeration and callbacks.
|
||||
*
|
||||
* The JNI functions do not clear the pending exceptions. This allows the
|
||||
* caller (Java code) to check and handle exceptions in the best possible
|
||||
* way.
|
||||
*/
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
|
||||
if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
|
||||
return 1;
|
||||
@ -250,11 +213,30 @@ static int CALLBACK EnumFontFacesInFamilyProcW(
|
||||
(*env)->ExceptionClear(env);
|
||||
return 1;
|
||||
}
|
||||
|
||||
(*env)->CallBooleanMethod(env, fmi->list, fmi->addMID, fullname);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
/* Delete the created reference before return */
|
||||
DeleteLocalReference(env, fullname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fullnameLC = (*env)->CallObjectMethod(env, fullname,
|
||||
fmi->toLowerCaseMID, fmi->locale);
|
||||
(*env)->CallBooleanMethod(env, fmi->list, fmi->addMID, fullname);
|
||||
/* Delete the created reference after its usage */
|
||||
DeleteLocalReference(env, fullname);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
(*env)->CallObjectMethod(env, fmi->fontToFamilyMap,
|
||||
fmi->putMID, fullnameLC, fmi->family);
|
||||
/* Delete the created reference after its usage */
|
||||
DeleteLocalReference(env, fullnameLC);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -270,62 +252,6 @@ static int CALLBACK EnumFontFacesInFamilyProcW(
|
||||
* Because we set fmi->list to be the newly created list the call back
|
||||
* can safely add to that list without a search.
|
||||
*/
|
||||
static int CALLBACK EnumFamilyNamesA(
|
||||
ENUMLOGFONTEXA *lpelfe, /* pointer to logical-font data */
|
||||
NEWTEXTMETRICEX *lpntme, /* pointer to physical-font data */
|
||||
int FontType, /* type of font */
|
||||
LPARAM lParam) /* application-defined data */
|
||||
{
|
||||
GdiFontMapInfo *fmi = (GdiFontMapInfo*)lParam;
|
||||
JNIEnv *env = fmi->env;
|
||||
jstring familyLC;
|
||||
LOGFONTA lfa;
|
||||
|
||||
/* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
|
||||
if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Windows lists fonts which have a vmtx (vertical metrics) table twice.
|
||||
* Once using their normal name, and again preceded by '@'. These appear
|
||||
* in font lists in some windows apps, such as wordpad. We don't want
|
||||
* these so we skip any font where the first character is '@'
|
||||
*/
|
||||
if (lpelfe->elfLogFont.lfFaceName[0] == '@') {
|
||||
return 1;
|
||||
}
|
||||
fmi->family = JNU_NewStringPlatform(env,lpelfe->elfLogFont.lfFaceName);
|
||||
if (fmi->family == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
return 1;
|
||||
}
|
||||
familyLC = (*env)->CallObjectMethod(env, fmi->family,
|
||||
fmi->toLowerCaseMID, fmi->locale);
|
||||
/* check if already seen this family with a different charset */
|
||||
if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap,
|
||||
fmi->containsKeyMID, familyLC)) {
|
||||
return 1;
|
||||
}
|
||||
fmi->list = (*env)->NewObject(env,
|
||||
fmi->arrayListClass, fmi->arrayListCtr, 4);
|
||||
if (fmi->list == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
return 1;
|
||||
}
|
||||
(*env)->CallObjectMethod(env, fmi->familyToFontListMap,
|
||||
fmi->putMID, familyLC, fmi->list);
|
||||
|
||||
/* printf("FAMILY=%s\n", lpelfe->elfLogFont.lfFaceName);fflush(stdout); */
|
||||
|
||||
memset(&lfa, 0, sizeof(lfa));
|
||||
strcpy(lfa.lfFaceName, lpelfe->elfLogFont.lfFaceName);
|
||||
lfa.lfCharSet = lpelfe->elfLogFont.lfCharSet;
|
||||
EnumFontFamiliesExA(screenDC, &lfa,
|
||||
(FONTENUMPROCA)EnumFontFacesInFamilyProcA,
|
||||
lParam, 0L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int CALLBACK EnumFamilyNamesW(
|
||||
ENUMLOGFONTEXW *lpelfe, /* pointer to logical-font data */
|
||||
NEWTEXTMETRICEX *lpntme, /* pointer to physical-font data */
|
||||
@ -338,6 +264,19 @@ static int CALLBACK EnumFamilyNamesW(
|
||||
size_t slen;
|
||||
LOGFONTW lfw;
|
||||
|
||||
/* Exceptions indicate critical errors such that program cannot continue
|
||||
* with further execution. Henceforth, the function returns immediately
|
||||
* on pending exceptions. In these situations, the function also returns
|
||||
* 0 indicating windows API to stop further enumeration and callbacks.
|
||||
*
|
||||
* The JNI functions do not clear the pending exceptions. This allows the
|
||||
* caller (Java code) to check and handle exceptions in the best possible
|
||||
* way.
|
||||
*/
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Both Vista and XP return DEVICE_FONTTYPE for OTF fonts */
|
||||
if (FontType != TRUETYPE_FONTTYPE && FontType != DEVICE_FONTTYPE) {
|
||||
return 1;
|
||||
@ -362,21 +301,51 @@ static int CALLBACK EnumFamilyNamesW(
|
||||
(*env)->ExceptionClear(env);
|
||||
return 1;
|
||||
}
|
||||
|
||||
familyLC = (*env)->CallObjectMethod(env, fmi->family,
|
||||
fmi->toLowerCaseMID, fmi->locale);
|
||||
/* Delete the created reference after its usage */
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
DeleteLocalReference(env, fmi->family);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check if already seen this family with a different charset */
|
||||
if ((*env)->CallBooleanMethod(env,fmi->familyToFontListMap,
|
||||
fmi->containsKeyMID, familyLC)) {
|
||||
jboolean mapHasKey = (*env)->CallBooleanMethod(env,
|
||||
fmi->familyToFontListMap,
|
||||
fmi->containsKeyMID,
|
||||
familyLC);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
/* Delete the created references before return */
|
||||
DeleteLocalReference(env, fmi->family);
|
||||
DeleteLocalReference(env, familyLC);
|
||||
return 0;
|
||||
} else if (mapHasKey) {
|
||||
/* Delete the created references before return */
|
||||
DeleteLocalReference(env, fmi->family);
|
||||
DeleteLocalReference(env, familyLC);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fmi->list = (*env)->NewObject(env,
|
||||
fmi->arrayListClass, fmi->arrayListCtr, 4);
|
||||
if (fmi->list == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
return 1;
|
||||
/* Delete the created references before return */
|
||||
DeleteLocalReference(env, fmi->family);
|
||||
DeleteLocalReference(env, familyLC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
(*env)->CallObjectMethod(env, fmi->familyToFontListMap,
|
||||
fmi->putMID, familyLC, fmi->list);
|
||||
/* Delete the created reference after its usage */
|
||||
DeleteLocalReference(env, familyLC);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
/* Delete the created reference before return */
|
||||
DeleteLocalReference(env, fmi->family);
|
||||
DeleteLocalReference(env, fmi->list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&lfw, 0, sizeof(lfw));
|
||||
wcscpy(lfw.lfFaceName, lpelfe->elfLogFont.lfFaceName);
|
||||
@ -384,10 +353,13 @@ static int CALLBACK EnumFamilyNamesW(
|
||||
EnumFontFamiliesExW(screenDC, &lfw,
|
||||
(FONTENUMPROCW)EnumFontFacesInFamilyProcW,
|
||||
lParam, 0L);
|
||||
|
||||
/* Delete the created reference after its usage in the enum function */
|
||||
DeleteLocalReference(env, fmi->family);
|
||||
DeleteLocalReference(env, fmi->list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* It looks like TrueType fonts have " (TrueType)" tacked on the end of their
|
||||
* name, so we can try to use that to distinguish TT from other fonts.
|
||||
* However if a program "installed" a font in the registry the key may
|
||||
@ -410,33 +382,6 @@ static int CALLBACK EnumFamilyNamesW(
|
||||
* Note: OpenType fonts seems to have " (TrueType)" suffix on Vista
|
||||
* but " (OpenType)" on XP.
|
||||
*/
|
||||
|
||||
static BOOL RegistryToBaseTTNameA(LPSTR name) {
|
||||
static const char TTSUFFIX[] = " (TrueType)";
|
||||
static const char OTSUFFIX[] = " (OpenType)";
|
||||
size_t TTSLEN = strlen(TTSUFFIX);
|
||||
char *suffix;
|
||||
|
||||
size_t len = strlen(name);
|
||||
if (len == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
if (name[len-1] != ')') {
|
||||
return FALSE;
|
||||
}
|
||||
if (len <= TTSLEN) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* suffix length is the same for truetype and opentype fonts */
|
||||
suffix = name + len - TTSLEN;
|
||||
if (strcmp(suffix, TTSUFFIX) == 0 || strcmp(suffix, OTSUFFIX) == 0) {
|
||||
suffix[0] = '\0'; /* truncate name */
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL RegistryToBaseTTNameW(LPWSTR name) {
|
||||
static const wchar_t TTSUFFIX[] = L" (TrueType)";
|
||||
static const wchar_t OTSUFFIX[] = L" (OpenType)";
|
||||
@ -462,71 +407,12 @@ static BOOL RegistryToBaseTTNameW(LPWSTR name) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void registerFontA(GdiFontMapInfo *fmi, jobject fontToFileMap,
|
||||
LPCSTR name, LPCSTR data) {
|
||||
LPSTR ptr1, ptr2;
|
||||
jstring fontStr;
|
||||
JNIEnv *env = fmi->env;
|
||||
size_t dslen = strlen(data);
|
||||
jstring fileStr = JNU_NewStringPlatform(env, data);
|
||||
if (fileStr == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
return;
|
||||
}
|
||||
|
||||
/* TTC or ttc means it may be a collection. Need to parse out
|
||||
* multiple font face names separated by " & "
|
||||
* By only doing this for fonts which look like collections based on
|
||||
* file name we are adhering to MS recommendations for font file names
|
||||
* so it seems that we can be sure that this identifies precisely
|
||||
* the MS-supplied truetype collections.
|
||||
* This avoids any potential issues if a TTF file happens to have
|
||||
* a & in the font name (I can't find anything which prohibits this)
|
||||
* and also means we only parse the key in cases we know to be
|
||||
* worthwhile.
|
||||
*/
|
||||
if ((data[dslen-1] == 'C' || data[dslen-1] == 'c') &&
|
||||
(ptr1 = strstr(name, " & ")) != NULL) {
|
||||
ptr1+=3;
|
||||
while (ptr1 >= name) { /* marginally safer than while (true) */
|
||||
while ((ptr2 = strstr(ptr1, " & ")) != NULL) {
|
||||
ptr1 = ptr2+3;
|
||||
}
|
||||
fontStr = JNU_NewStringPlatform(env, ptr1);
|
||||
if (fontStr == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
return;
|
||||
}
|
||||
fontStr = (*env)->CallObjectMethod(env, fontStr,
|
||||
fmi->toLowerCaseMID,
|
||||
fmi->locale);
|
||||
(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
|
||||
fontStr, fileStr);
|
||||
if (ptr1 == name) {
|
||||
break;
|
||||
} else {
|
||||
*(ptr1-3) ='\0';
|
||||
ptr1 = (LPSTR)name;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fontStr = JNU_NewStringPlatform(env, name);
|
||||
if (fontStr == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
return;
|
||||
}
|
||||
fontStr = (*env)->CallObjectMethod(env, fontStr,
|
||||
fmi->toLowerCaseMID, fmi->locale);
|
||||
(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
|
||||
fontStr, fileStr);
|
||||
}
|
||||
}
|
||||
|
||||
static void registerFontW(GdiFontMapInfo *fmi, jobject fontToFileMap,
|
||||
LPWSTR name, LPWSTR data) {
|
||||
|
||||
wchar_t *ptr1, *ptr2;
|
||||
jstring fontStr;
|
||||
jstring fontStrLC;
|
||||
JNIEnv *env = fmi->env;
|
||||
size_t dslen = wcslen(data);
|
||||
jstring fileStr = (*env)->NewString(env, data, (jsize)dslen);
|
||||
@ -557,13 +443,32 @@ static void registerFontW(GdiFontMapInfo *fmi, jobject fontToFileMap,
|
||||
fontStr = (*env)->NewString(env, ptr1, (jsize)wcslen(ptr1));
|
||||
if (fontStr == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
/* Delete the created reference before return */
|
||||
DeleteLocalReference(env, fileStr);
|
||||
return;
|
||||
}
|
||||
fontStr = (*env)->CallObjectMethod(env, fontStr,
|
||||
fmi->toLowerCaseMID,
|
||||
fmi->locale);
|
||||
|
||||
fontStrLC = (*env)->CallObjectMethod(env, fontStr,
|
||||
fmi->toLowerCaseMID,
|
||||
fmi->locale);
|
||||
/* Delete the created reference after its usage */
|
||||
DeleteLocalReference(env, fontStr);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
/* Delete the created reference before return */
|
||||
DeleteLocalReference(env, fileStr);
|
||||
return;
|
||||
}
|
||||
|
||||
(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
|
||||
fontStr, fileStr);
|
||||
fontStrLC, fileStr);
|
||||
/* Delete the reference after its usage */
|
||||
DeleteLocalReference(env, fontStrLC);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
/* Delete the created reference before return */
|
||||
DeleteLocalReference(env, fileStr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr1 == name) {
|
||||
break;
|
||||
} else {
|
||||
@ -575,13 +480,34 @@ static void registerFontW(GdiFontMapInfo *fmi, jobject fontToFileMap,
|
||||
fontStr = (*env)->NewString(env, name, (jsize)wcslen(name));
|
||||
if (fontStr == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
/* Delete the created reference before return */
|
||||
DeleteLocalReference(env, fileStr);
|
||||
return;
|
||||
}
|
||||
fontStr = (*env)->CallObjectMethod(env, fontStr,
|
||||
|
||||
fontStrLC = (*env)->CallObjectMethod(env, fontStr,
|
||||
fmi->toLowerCaseMID, fmi->locale);
|
||||
/* Delete the created reference after its usage */
|
||||
DeleteLocalReference(env, fontStr);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
/* Delete the created reference before return */
|
||||
DeleteLocalReference(env, fileStr);
|
||||
return;
|
||||
}
|
||||
|
||||
(*env)->CallObjectMethod(env, fontToFileMap, fmi->putMID,
|
||||
fontStr, fileStr);
|
||||
fontStrLC, fileStr);
|
||||
/* Delete the created reference after its usage */
|
||||
DeleteLocalReference(env, fontStrLC);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
/* Delete the created reference before return */
|
||||
DeleteLocalReference(env, fileStr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete the created reference after its usage */
|
||||
DeleteLocalReference(env, fileStr);
|
||||
}
|
||||
|
||||
/* Obtain all the fontname -> filename mappings.
|
||||
@ -595,7 +521,6 @@ Java_sun_awt_Win32FontManager_populateFontFileNameMap0
|
||||
{
|
||||
#define MAX_BUFFER (FILENAME_MAX+1)
|
||||
const wchar_t wname[MAX_BUFFER];
|
||||
const char cname[MAX_BUFFER];
|
||||
const char data[MAX_BUFFER];
|
||||
|
||||
DWORD type;
|
||||
@ -604,10 +529,10 @@ Java_sun_awt_Win32FontManager_populateFontFileNameMap0
|
||||
DWORD dwNameSize;
|
||||
DWORD dwDataValueSize;
|
||||
DWORD nval;
|
||||
LPCSTR fontKeyName;
|
||||
DWORD dwNumValues, dwMaxValueNameLen, dwMaxValueDataLen;
|
||||
DWORD numValues = 0;
|
||||
jclass classID;
|
||||
jclass classIDHashMap;
|
||||
jclass classIDString;
|
||||
jmethodID putMID;
|
||||
GdiFontMapInfo fmi;
|
||||
|
||||
@ -619,11 +544,11 @@ Java_sun_awt_Win32FontManager_populateFontFileNameMap0
|
||||
familyToFontListMap == NULL) {
|
||||
return;
|
||||
}
|
||||
classID = (*env)->FindClass(env, "java/util/HashMap");
|
||||
if (classID == NULL) {
|
||||
classIDHashMap = (*env)->FindClass(env, "java/util/HashMap");
|
||||
if (classIDHashMap == NULL) {
|
||||
return;
|
||||
}
|
||||
putMID = (*env)->GetMethodID(env, classID, "put",
|
||||
putMID = (*env)->GetMethodID(env, classIDHashMap, "put",
|
||||
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
if (putMID == NULL) {
|
||||
return;
|
||||
@ -634,7 +559,8 @@ Java_sun_awt_Win32FontManager_populateFontFileNameMap0
|
||||
fmi.familyToFontListMap = familyToFontListMap;
|
||||
fmi.putMID = putMID;
|
||||
fmi.locale = locale;
|
||||
fmi.containsKeyMID = (*env)->GetMethodID(env, classID, "containsKey",
|
||||
fmi.containsKeyMID = (*env)->GetMethodID(env, classIDHashMap,
|
||||
"containsKey",
|
||||
"(Ljava/lang/Object;)Z");
|
||||
if (fmi.containsKeyMID == NULL) {
|
||||
return;
|
||||
@ -654,12 +580,13 @@ Java_sun_awt_Win32FontManager_populateFontFileNameMap0
|
||||
if (fmi.addMID == NULL) {
|
||||
return;
|
||||
}
|
||||
classID = (*env)->FindClass(env, "java/lang/String");
|
||||
if (classID == NULL) {
|
||||
|
||||
classIDString = (*env)->FindClass(env, "java/lang/String");
|
||||
if (classIDString == NULL) {
|
||||
return;
|
||||
}
|
||||
fmi.toLowerCaseMID =
|
||||
(*env)->GetMethodID(env, classID, "toLowerCase",
|
||||
(*env)->GetMethodID(env, classIDString, "toLowerCase",
|
||||
"(Ljava/util/Locale;)Ljava/lang/String;");
|
||||
if (fmi.toLowerCaseMID == NULL) {
|
||||
return;
|
||||
@ -669,44 +596,29 @@ Java_sun_awt_Win32FontManager_populateFontFileNameMap0
|
||||
if (screenDC == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enumerate fonts via GDI to build maps of fonts and families */
|
||||
if (IS_NT) {
|
||||
LOGFONTW lfw;
|
||||
memset(&lfw, 0, sizeof(lfw));
|
||||
lfw.lfCharSet = DEFAULT_CHARSET; /* all charsets */
|
||||
wcscpy(lfw.lfFaceName, L""); /* one face per family (CHECK) */
|
||||
EnumFontFamiliesExW(screenDC, &lfw,
|
||||
(FONTENUMPROCW)EnumFamilyNamesW,
|
||||
(LPARAM)(&fmi), 0L);
|
||||
} else {
|
||||
LOGFONT lfa;
|
||||
memset(&lfa, 0, sizeof(lfa));
|
||||
lfa.lfCharSet = DEFAULT_CHARSET; /* all charsets */
|
||||
strcpy(lfa.lfFaceName, ""); /* one face per family */
|
||||
ret = EnumFontFamiliesExA(screenDC, &lfa,
|
||||
(FONTENUMPROCA)EnumFamilyNamesA,
|
||||
(LPARAM)(&fmi), 0L);
|
||||
}
|
||||
LOGFONTW lfw;
|
||||
memset(&lfw, 0, sizeof(lfw));
|
||||
lfw.lfCharSet = DEFAULT_CHARSET; /* all charsets */
|
||||
wcscpy(lfw.lfFaceName, L""); /* one face per family (CHECK) */
|
||||
EnumFontFamiliesExW(screenDC, &lfw,
|
||||
(FONTENUMPROCW)EnumFamilyNamesW,
|
||||
(LPARAM)(&fmi), 0L);
|
||||
|
||||
/* Use the windows registry to map font names to files */
|
||||
fontKeyName = (IS_NT) ? FONTKEY_NT : FONTKEY_WIN;
|
||||
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
fontKeyName, 0L, KEY_READ, &hkeyFonts);
|
||||
FONTKEY_NT, 0L, KEY_READ, &hkeyFonts);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
ReleaseDC(NULL, screenDC);
|
||||
screenDC = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (IS_NT) {
|
||||
ret = RegQueryInfoKeyW(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
&dwNumValues, &dwMaxValueNameLen,
|
||||
&dwMaxValueDataLen, NULL, NULL);
|
||||
} else {
|
||||
ret = RegQueryInfoKeyA(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
&dwNumValues, &dwMaxValueNameLen,
|
||||
&dwMaxValueDataLen, NULL, NULL);
|
||||
}
|
||||
ret = RegQueryInfoKeyW(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
&dwNumValues, &dwMaxValueNameLen,
|
||||
&dwMaxValueDataLen, NULL, NULL);
|
||||
|
||||
if (ret != ERROR_SUCCESS ||
|
||||
dwMaxValueNameLen >= MAX_BUFFER ||
|
||||
dwMaxValueDataLen >= MAX_BUFFER) {
|
||||
@ -718,39 +630,30 @@ Java_sun_awt_Win32FontManager_populateFontFileNameMap0
|
||||
for (nval = 0; nval < dwNumValues; nval++ ) {
|
||||
dwNameSize = MAX_BUFFER;
|
||||
dwDataValueSize = MAX_BUFFER;
|
||||
if (IS_NT) {
|
||||
ret = RegEnumValueW(hkeyFonts, nval, (LPWSTR)wname, &dwNameSize,
|
||||
NULL, &type, (LPBYTE)data, &dwDataValueSize);
|
||||
} else {
|
||||
ret = RegEnumValueA(hkeyFonts, nval, (LPSTR)cname, &dwNameSize,
|
||||
NULL, &type, (LPBYTE)data, &dwDataValueSize);
|
||||
}
|
||||
ret = RegEnumValueW(hkeyFonts, nval, (LPWSTR)wname, &dwNameSize,
|
||||
NULL, &type, (LPBYTE)data, &dwDataValueSize);
|
||||
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
if (type != REG_SZ) { /* REG_SZ means a null-terminated string */
|
||||
continue;
|
||||
}
|
||||
if (IS_NT) {
|
||||
if (!RegistryToBaseTTNameW((LPWSTR)wname) ) {
|
||||
/* If the filename ends with ".ttf" or ".otf" also accept it.
|
||||
* Not expecting to need to do this for .ttc files.
|
||||
* Also note this code is not mirrored in the "A" (win9x) path.
|
||||
*/
|
||||
LPWSTR dot = wcsrchr((LPWSTR)data, L'.');
|
||||
if (dot == NULL || ((wcsicmp(dot, L".ttf") != 0)
|
||||
&& (wcsicmp(dot, L".otf") != 0))) {
|
||||
continue; /* not a TT font... */
|
||||
}
|
||||
|
||||
if (!RegistryToBaseTTNameW((LPWSTR)wname) ) {
|
||||
/* If the filename ends with ".ttf" or ".otf" also accept it.
|
||||
* Not expecting to need to do this for .ttc files.
|
||||
* Also note this code is not mirrored in the "A" (win9x) path.
|
||||
*/
|
||||
LPWSTR dot = wcsrchr((LPWSTR)data, L'.');
|
||||
if (dot == NULL || ((wcsicmp(dot, L".ttf") != 0)
|
||||
&& (wcsicmp(dot, L".otf") != 0))) {
|
||||
continue; /* not a TT font... */
|
||||
}
|
||||
registerFontW(&fmi, fontToFileMap, (LPWSTR)wname, (LPWSTR)data);
|
||||
} else {
|
||||
if (!RegistryToBaseTTNameA((LPSTR)cname)) {
|
||||
continue; /* not a TT font... */
|
||||
}
|
||||
registerFontA(&fmi, fontToFileMap, cname, (LPCSTR)data);
|
||||
}
|
||||
registerFontW(&fmi, fontToFileMap, (LPWSTR)wname, (LPWSTR)data);
|
||||
}
|
||||
|
||||
RegCloseKey(hkeyFonts);
|
||||
ReleaseDC(NULL, screenDC);
|
||||
screenDC = NULL;
|
||||
|
@ -39,6 +39,7 @@ import java.security.PrivilegedAction;
|
||||
|
||||
import com.sun.jndi.ldap.pool.PoolCleaner;
|
||||
import com.sun.jndi.ldap.pool.Pool;
|
||||
import jdk.internal.misc.InnocuousThread;
|
||||
|
||||
/**
|
||||
* Contains utilities for managing connection pools of LdapClient.
|
||||
@ -163,7 +164,17 @@ public final class LdapPoolManager {
|
||||
|
||||
if (idleTimeout > 0) {
|
||||
// Create cleaner to expire idle connections
|
||||
new PoolCleaner(idleTimeout, pools).start();
|
||||
PrivilegedAction<Void> pa = new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
Thread t = InnocuousThread.newSystemThread(
|
||||
"LDAP PoolCleaner",
|
||||
new PoolCleaner(idleTimeout, pools));
|
||||
assert t.getContextClassLoader() == null;
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
return null;
|
||||
}};
|
||||
AccessController.doPrivileged(pa);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
|
@ -30,7 +30,7 @@ package com.sun.jndi.ldap.pool;
|
||||
*
|
||||
* @author Rosanna Lee
|
||||
*/
|
||||
final public class PoolCleaner extends Thread {
|
||||
final public class PoolCleaner implements Runnable {
|
||||
final private Pool[] pools;
|
||||
final private long period;
|
||||
|
||||
@ -42,9 +42,9 @@ final public class PoolCleaner extends Thread {
|
||||
super();
|
||||
this.period = period;
|
||||
this.pools = pools.clone();
|
||||
setDaemon(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
long threshold;
|
||||
while (true) {
|
||||
|
@ -29,6 +29,7 @@ import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import jdk.internal.misc.InnocuousThread;
|
||||
|
||||
|
||||
/**
|
||||
@ -90,8 +91,9 @@ class GC {
|
||||
}});
|
||||
}
|
||||
|
||||
private static class Daemon extends Thread {
|
||||
private static class Daemon implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (;;) {
|
||||
long l;
|
||||
@ -129,23 +131,17 @@ class GC {
|
||||
}
|
||||
}
|
||||
|
||||
private Daemon(ThreadGroup tg) {
|
||||
super(tg, null, "GC Daemon", 0L, false);
|
||||
}
|
||||
|
||||
/* Create a new daemon thread in the root thread group */
|
||||
/* Create a new daemon thread */
|
||||
public static void create() {
|
||||
PrivilegedAction<Void> pa = new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
ThreadGroup tg = Thread.currentThread().getThreadGroup();
|
||||
for (ThreadGroup tgn = tg;
|
||||
tgn != null;
|
||||
tg = tgn, tgn = tg.getParent());
|
||||
Daemon d = new Daemon(tg);
|
||||
d.setDaemon(true);
|
||||
d.setPriority(Thread.MIN_PRIORITY + 1);
|
||||
d.start();
|
||||
GC.daemon = d;
|
||||
Thread t = InnocuousThread.newSystemThread("RMI GC Daemon",
|
||||
new Daemon());
|
||||
assert t.getContextClassLoader() == null;
|
||||
t.setDaemon(true);
|
||||
t.setPriority(Thread.MIN_PRIORITY + 1);
|
||||
t.start();
|
||||
GC.daemon = t;
|
||||
return null;
|
||||
}};
|
||||
AccessController.doPrivileged(pa);
|
||||
|
@ -39,8 +39,6 @@ import javax.xml.crypto.XMLStructure;
|
||||
import javax.xml.crypto.XMLCryptoContext;
|
||||
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
|
||||
|
||||
import sun.security.jca.*;
|
||||
import sun.security.jca.GetInstance.Instance;
|
||||
|
||||
/**
|
||||
* A Service Provider Interface for transform and canonicalization algorithms.
|
||||
@ -165,18 +163,23 @@ public abstract class TransformService implements Transform {
|
||||
if (mechanismType.equals("DOM")) {
|
||||
dom = true;
|
||||
}
|
||||
List<Service> services = GetInstance.getServices("TransformService", algorithm);
|
||||
for (Iterator<Service> t = services.iterator(); t.hasNext(); ) {
|
||||
Service s = t.next();
|
||||
String value = s.getAttribute("MechanismType");
|
||||
if ((value == null && dom) ||
|
||||
(value != null && value.equals(mechanismType))) {
|
||||
Instance instance = GetInstance.getInstance(s, null);
|
||||
TransformService ts = (TransformService) instance.impl;
|
||||
ts.algorithm = algorithm;
|
||||
ts.mechanism = mechanismType;
|
||||
ts.provider = instance.provider;
|
||||
return ts;
|
||||
|
||||
Provider[] provs = Security.getProviders();
|
||||
for (Provider p : provs) {
|
||||
Service s = p.getService("TransformService", algorithm);
|
||||
if (s != null) {
|
||||
String value = s.getAttribute("MechanismType");
|
||||
if ((value == null && dom) ||
|
||||
(value != null && value.equals(mechanismType))) {
|
||||
Object obj = s.newInstance(null);
|
||||
if (obj instanceof TransformService) {
|
||||
TransformService ts = (TransformService) obj;
|
||||
ts.algorithm = algorithm;
|
||||
ts.mechanism = mechanismType;
|
||||
ts.provider = p;
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new NoSuchAlgorithmException
|
||||
@ -215,21 +218,24 @@ public abstract class TransformService implements Transform {
|
||||
if (mechanismType.equals("DOM")) {
|
||||
dom = true;
|
||||
}
|
||||
Service s = GetInstance.getService
|
||||
("TransformService", algorithm, provider);
|
||||
String value = s.getAttribute("MechanismType");
|
||||
if ((value == null && dom) ||
|
||||
(value != null && value.equals(mechanismType))) {
|
||||
Instance instance = GetInstance.getInstance(s, null);
|
||||
TransformService ts = (TransformService) instance.impl;
|
||||
ts.algorithm = algorithm;
|
||||
ts.mechanism = mechanismType;
|
||||
ts.provider = instance.provider;
|
||||
return ts;
|
||||
Service s = provider.getService("TransformService", algorithm);
|
||||
if (s != null) {
|
||||
String value = s.getAttribute("MechanismType");
|
||||
if ((value == null && dom) ||
|
||||
(value != null && value.equals(mechanismType))) {
|
||||
Object obj = s.newInstance(null);
|
||||
if (obj instanceof TransformService) {
|
||||
TransformService ts = (TransformService) obj;
|
||||
ts.algorithm = algorithm;
|
||||
ts.mechanism = mechanismType;
|
||||
ts.provider = provider;
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new NoSuchAlgorithmException
|
||||
(algorithm + " algorithm and " + mechanismType
|
||||
+ " mechanism not available");
|
||||
+ " mechanism not available from " + provider.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -268,21 +274,25 @@ public abstract class TransformService implements Transform {
|
||||
if (mechanismType.equals("DOM")) {
|
||||
dom = true;
|
||||
}
|
||||
Service s = GetInstance.getService
|
||||
("TransformService", algorithm, provider);
|
||||
String value = s.getAttribute("MechanismType");
|
||||
if ((value == null && dom) ||
|
||||
(value != null && value.equals(mechanismType))) {
|
||||
Instance instance = GetInstance.getInstance(s, null);
|
||||
TransformService ts = (TransformService) instance.impl;
|
||||
ts.algorithm = algorithm;
|
||||
ts.mechanism = mechanismType;
|
||||
ts.provider = instance.provider;
|
||||
return ts;
|
||||
Provider p = Security.getProvider(provider);
|
||||
Service s = p.getService("TransformService", algorithm);
|
||||
if (s != null) {
|
||||
String value = s.getAttribute("MechanismType");
|
||||
if ((value == null && dom) ||
|
||||
(value != null && value.equals(mechanismType))) {
|
||||
Object obj = s.newInstance(null);
|
||||
if (obj instanceof TransformService) {
|
||||
TransformService ts = (TransformService) obj;
|
||||
ts.algorithm = algorithm;
|
||||
ts.mechanism = mechanismType;
|
||||
ts.provider = p;
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new NoSuchAlgorithmException
|
||||
(algorithm + " algorithm and " + mechanismType
|
||||
+ " mechanism not available");
|
||||
+ " mechanism not available from " + provider);
|
||||
}
|
||||
|
||||
private static class MechanismMapEntry implements Map.Entry<String,String> {
|
||||
|
@ -43,11 +43,10 @@ import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.Provider;
|
||||
import java.security.Provider.Service;
|
||||
import java.security.Security;
|
||||
import java.util.List;
|
||||
|
||||
import sun.security.jca.*;
|
||||
import sun.security.jca.GetInstance.Instance;
|
||||
|
||||
/**
|
||||
* A factory for creating {@link XMLSignature} objects from scratch or
|
||||
@ -198,17 +197,26 @@ public abstract class XMLSignatureFactory {
|
||||
if (mechanismType == null) {
|
||||
throw new NullPointerException("mechanismType cannot be null");
|
||||
}
|
||||
Instance instance;
|
||||
try {
|
||||
instance = GetInstance.getInstance
|
||||
("XMLSignatureFactory", null, mechanismType);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new NoSuchMechanismException(nsae);
|
||||
Provider[] provs = Security.getProviders();
|
||||
for (Provider p : provs) {
|
||||
Service s = p.getService("XMLSignatureFactory", mechanismType);
|
||||
if (s != null) {
|
||||
Object obj = null;
|
||||
try {
|
||||
obj = s.newInstance(null);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new NoSuchMechanismException(nsae);
|
||||
}
|
||||
if (obj instanceof XMLSignatureFactory) {
|
||||
XMLSignatureFactory factory = (XMLSignatureFactory) obj;
|
||||
factory.mechanismType = mechanismType;
|
||||
factory.provider = p;
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
}
|
||||
XMLSignatureFactory factory = (XMLSignatureFactory) instance.impl;
|
||||
factory.mechanismType = mechanismType;
|
||||
factory.provider = instance.provider;
|
||||
return factory;
|
||||
throw new NoSuchMechanismException
|
||||
("Mechanism " + mechanismType + " not available");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -240,17 +248,25 @@ public abstract class XMLSignatureFactory {
|
||||
throw new NullPointerException("provider cannot be null");
|
||||
}
|
||||
|
||||
Instance instance;
|
||||
try {
|
||||
instance = GetInstance.getInstance
|
||||
("XMLSignatureFactory", null, mechanismType, provider);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new NoSuchMechanismException(nsae);
|
||||
Service s = provider.getService("XMLSignatureFactory", mechanismType);
|
||||
if (s != null) {
|
||||
Object obj = null;
|
||||
try {
|
||||
obj = s.newInstance(null);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new NoSuchMechanismException(nsae);
|
||||
}
|
||||
|
||||
if (obj instanceof XMLSignatureFactory) {
|
||||
XMLSignatureFactory factory = (XMLSignatureFactory) obj;
|
||||
factory.mechanismType = mechanismType;
|
||||
factory.provider = provider;
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
XMLSignatureFactory factory = (XMLSignatureFactory) instance.impl;
|
||||
factory.mechanismType = mechanismType;
|
||||
factory.provider = instance.provider;
|
||||
return factory;
|
||||
throw new NoSuchMechanismException
|
||||
("Mechanism " + mechanismType + " not available from " +
|
||||
provider.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -288,17 +304,24 @@ public abstract class XMLSignatureFactory {
|
||||
throw new NoSuchProviderException();
|
||||
}
|
||||
|
||||
Instance instance;
|
||||
try {
|
||||
instance = GetInstance.getInstance
|
||||
("XMLSignatureFactory", null, mechanismType, provider);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new NoSuchMechanismException(nsae);
|
||||
Provider p = Security.getProvider(provider);
|
||||
Service s = p.getService("XMLSignatureFactory", mechanismType);
|
||||
if (s != null) {
|
||||
Object obj = null;
|
||||
try {
|
||||
obj = s.newInstance(null);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new NoSuchMechanismException(nsae);
|
||||
}
|
||||
if (obj instanceof XMLSignatureFactory) {
|
||||
XMLSignatureFactory factory = (XMLSignatureFactory) obj;
|
||||
factory.mechanismType = mechanismType;
|
||||
factory.provider = p;
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
XMLSignatureFactory factory = (XMLSignatureFactory) instance.impl;
|
||||
factory.mechanismType = mechanismType;
|
||||
factory.provider = instance.provider;
|
||||
return factory;
|
||||
throw new NoSuchMechanismException
|
||||
("Mechanism " + mechanismType + " not available from " + provider);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,6 +32,7 @@ import java.security.KeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.Provider;
|
||||
import java.security.Provider.Service;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Security;
|
||||
import java.security.cert.X509CRL;
|
||||
@ -43,8 +44,6 @@ import javax.xml.crypto.XMLStructure;
|
||||
import javax.xml.crypto.dom.DOMStructure;
|
||||
import javax.xml.crypto.dsig.*;
|
||||
|
||||
import sun.security.jca.*;
|
||||
import sun.security.jca.GetInstance.Instance;
|
||||
|
||||
/**
|
||||
* A factory for creating {@link KeyInfo} objects from scratch or for
|
||||
@ -153,17 +152,26 @@ public abstract class KeyInfoFactory {
|
||||
if (mechanismType == null) {
|
||||
throw new NullPointerException("mechanismType cannot be null");
|
||||
}
|
||||
Instance instance;
|
||||
try {
|
||||
instance = GetInstance.getInstance
|
||||
("KeyInfoFactory", null, mechanismType);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new NoSuchMechanismException(nsae);
|
||||
Provider[] provs = Security.getProviders();
|
||||
for (Provider p : provs) {
|
||||
Service s = p.getService("KeyInfoFactory", mechanismType);
|
||||
if (s != null) {
|
||||
Object obj = null;
|
||||
try {
|
||||
obj = s.newInstance(null);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new NoSuchMechanismException(nsae);
|
||||
}
|
||||
if (obj instanceof KeyInfoFactory) {
|
||||
KeyInfoFactory factory = (KeyInfoFactory) obj;
|
||||
factory.mechanismType = mechanismType;
|
||||
factory.provider = p;
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
}
|
||||
KeyInfoFactory factory = (KeyInfoFactory) instance.impl;
|
||||
factory.mechanismType = mechanismType;
|
||||
factory.provider = instance.provider;
|
||||
return factory;
|
||||
throw new NoSuchMechanismException
|
||||
("Mechanism " + mechanismType + " not available");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -195,17 +203,24 @@ public abstract class KeyInfoFactory {
|
||||
throw new NullPointerException("provider cannot be null");
|
||||
}
|
||||
|
||||
Instance instance;
|
||||
try {
|
||||
instance = GetInstance.getInstance
|
||||
("KeyInfoFactory", null, mechanismType, provider);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new NoSuchMechanismException(nsae);
|
||||
Service s = provider.getService("KeyInfoFactory", mechanismType);
|
||||
if (s != null) {
|
||||
Object obj = null;
|
||||
try {
|
||||
obj = s.newInstance(null);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new NoSuchMechanismException(nsae);
|
||||
}
|
||||
|
||||
if (obj instanceof KeyInfoFactory) {
|
||||
KeyInfoFactory factory = (KeyInfoFactory) obj;
|
||||
factory.mechanismType = mechanismType;
|
||||
factory.provider = provider;
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
KeyInfoFactory factory = (KeyInfoFactory) instance.impl;
|
||||
factory.mechanismType = mechanismType;
|
||||
factory.provider = instance.provider;
|
||||
return factory;
|
||||
throw new NoSuchMechanismException
|
||||
("Mechanism " + mechanismType + " not available from " + provider.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -242,18 +257,24 @@ public abstract class KeyInfoFactory {
|
||||
} else if (provider.length() == 0) {
|
||||
throw new NoSuchProviderException();
|
||||
}
|
||||
|
||||
Instance instance;
|
||||
try {
|
||||
instance = GetInstance.getInstance
|
||||
("KeyInfoFactory", null, mechanismType, provider);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new NoSuchMechanismException(nsae);
|
||||
Provider p = Security.getProvider(provider);
|
||||
Service s = p.getService("KeyInfoFactory", mechanismType);
|
||||
if (s != null) {
|
||||
Object obj = null;
|
||||
try {
|
||||
obj = s.newInstance(null);
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new NoSuchMechanismException(nsae);
|
||||
}
|
||||
if (obj instanceof KeyInfoFactory) {
|
||||
KeyInfoFactory factory = (KeyInfoFactory) obj;
|
||||
factory.mechanismType = mechanismType;
|
||||
factory.provider = p;
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
KeyInfoFactory factory = (KeyInfoFactory) instance.impl;
|
||||
factory.mechanismType = mechanismType;
|
||||
factory.provider = instance.provider;
|
||||
return factory;
|
||||
throw new NoSuchMechanismException
|
||||
("Mechanism " + mechanismType + " not available from " + provider);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,8 +58,8 @@ import jdk.tools.jlink.internal.BasicImageWriter;
|
||||
import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
|
||||
import jdk.tools.jlink.internal.plugins.FileCopierPlugin.SymImageFile;
|
||||
import jdk.tools.jlink.internal.ExecutableImage;
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
import jdk.tools.jlink.plugin.PluginException;
|
||||
|
||||
/**
|
||||
@ -170,10 +170,10 @@ public final class DefaultImageBuilder implements ImageBuilder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeFiles(ModulePool files) {
|
||||
public void storeFiles(ResourcePool files) {
|
||||
try {
|
||||
files.entries().forEach(f -> {
|
||||
if (!f.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
|
||||
if (!f.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
|
||||
try {
|
||||
accept(f);
|
||||
} catch (IOException ioExp) {
|
||||
@ -181,17 +181,17 @@ public final class DefaultImageBuilder implements ImageBuilder {
|
||||
}
|
||||
}
|
||||
});
|
||||
files.modules().forEach(m -> {
|
||||
files.moduleView().modules().forEach(m -> {
|
||||
// Only add modules that contain packages
|
||||
if (!m.getAllPackages().isEmpty()) {
|
||||
if (!m.packages().isEmpty()) {
|
||||
// Skip the fake module used by FileCopierPlugin when copying files.
|
||||
if (m.getName().equals(FileCopierPlugin.FAKE_MODULE)) {
|
||||
if (m.name().equals(FileCopierPlugin.FAKE_MODULE)) {
|
||||
return;
|
||||
}
|
||||
modules.add(m.getName());
|
||||
modules.add(m.name());
|
||||
}
|
||||
});
|
||||
storeFiles(modules, files.getReleaseProperties());
|
||||
storeFiles(modules, files.releaseProperties());
|
||||
|
||||
if (Files.getFileStore(root).supportsFileAttributeView(PosixFileAttributeView.class)) {
|
||||
// launchers in the bin directory need execute permission
|
||||
@ -226,16 +226,16 @@ public final class DefaultImageBuilder implements ImageBuilder {
|
||||
* @param modules The set of modules that the runtime image contains.
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void prepareApplicationFiles(ModulePool imageContent, Set<String> modules) throws IOException {
|
||||
protected void prepareApplicationFiles(ResourcePool imageContent, Set<String> modules) throws IOException {
|
||||
// generate launch scripts for the modules with a main class
|
||||
for (String module : modules) {
|
||||
String path = "/" + module + "/module-info.class";
|
||||
Optional<ModuleEntry> res = imageContent.findEntry(path);
|
||||
Optional<ResourcePoolEntry> res = imageContent.findEntry(path);
|
||||
if (!res.isPresent()) {
|
||||
throw new IOException("module-info.class not found for " + module + " module");
|
||||
}
|
||||
Optional<String> mainClass;
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(res.get().getBytes());
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(res.get().contentBytes());
|
||||
mainClass = ModuleDescriptor.read(stream).mainClass();
|
||||
if (mainClass.isPresent()) {
|
||||
Path cmd = root.resolve("bin").resolve(module);
|
||||
@ -298,14 +298,14 @@ public final class DefaultImageBuilder implements ImageBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private void accept(ModuleEntry file) throws IOException {
|
||||
String fullPath = file.getPath();
|
||||
String module = "/" + file.getModule() + "/";
|
||||
private void accept(ResourcePoolEntry file) throws IOException {
|
||||
String fullPath = file.path();
|
||||
String module = "/" + file.moduleName() + "/";
|
||||
String filename = fullPath.substring(module.length());
|
||||
// Remove radical native|config|...
|
||||
filename = filename.substring(filename.indexOf('/') + 1);
|
||||
try (InputStream in = file.stream()) {
|
||||
switch (file.getType()) {
|
||||
try (InputStream in = file.content()) {
|
||||
switch (file.type()) {
|
||||
case NATIVE_LIB:
|
||||
writeEntry(in, destFile(nativeDir(filename), filename));
|
||||
break;
|
||||
|
@ -29,7 +29,7 @@ import java.util.Properties;
|
||||
|
||||
import jdk.tools.jlink.internal.ExecutableImage;
|
||||
import jdk.tools.jlink.plugin.PluginException;
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
|
||||
/**
|
||||
* Implement this interface to develop your own image layout. First the jimage
|
||||
@ -45,7 +45,7 @@ public interface ImageBuilder {
|
||||
* @param release the release properties
|
||||
* @throws PluginException
|
||||
*/
|
||||
public default void storeFiles(ModulePool content, Properties release) {
|
||||
public default void storeFiles(ResourcePool content, Properties release) {
|
||||
storeFiles(content);
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ public interface ImageBuilder {
|
||||
* @param content Pool of module content.
|
||||
* @throws PluginException
|
||||
*/
|
||||
public default void storeFiles(ModulePool content) {
|
||||
public default void storeFiles(ResourcePool content) {
|
||||
throw new UnsupportedOperationException("storeFiles");
|
||||
}
|
||||
|
||||
|
@ -26,14 +26,14 @@
|
||||
package jdk.tools.jlink.internal;
|
||||
|
||||
import java.util.Objects;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
|
||||
/**
|
||||
* A LinkModuleEntry is the elementary unit of data inside an image. It is
|
||||
* A LinkResourcePoolEntry is the elementary unit of data inside an image. It is
|
||||
* generally a file. e.g.: a java class file, a resource file, a shared library,
|
||||
* ...
|
||||
* <br>
|
||||
* A LinkModuleEntry is identified by a path of the form:
|
||||
* A LinkResourcePoolEntry is identified by a path of the form:
|
||||
* <ul>
|
||||
* <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file
|
||||
* name}</li>
|
||||
@ -41,36 +41,36 @@ import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
* {@literal bin|conf|native}/{dir1}>/.../{dirN}/{file name}</li>
|
||||
* </ul>
|
||||
*/
|
||||
abstract class AbstractModuleEntry implements ModuleEntry {
|
||||
abstract class AbstractResourcePoolEntry implements ResourcePoolEntry {
|
||||
private final String path;
|
||||
private final String module;
|
||||
private final Type type;
|
||||
|
||||
/**
|
||||
* Create a new AbstractModuleEntry.
|
||||
* Create a new AbstractResourcePoolEntry.
|
||||
*
|
||||
* @param module The module name.
|
||||
* @param path The data path identifier.
|
||||
* @param type The data type.
|
||||
*/
|
||||
AbstractModuleEntry(String module, String path, Type type) {
|
||||
AbstractResourcePoolEntry(String module, String path, Type type) {
|
||||
this.module = Objects.requireNonNull(module);
|
||||
this.path = Objects.requireNonNull(path);
|
||||
this.type = Objects.requireNonNull(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getModule() {
|
||||
public final String moduleName() {
|
||||
return module;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getPath() {
|
||||
public final String path() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Type getType() {
|
||||
public final Type type() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -81,15 +81,15 @@ abstract class AbstractModuleEntry implements ModuleEntry {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof AbstractModuleEntry)) {
|
||||
if (!(other instanceof AbstractResourcePoolEntry)) {
|
||||
return false;
|
||||
}
|
||||
AbstractModuleEntry f = (AbstractModuleEntry) other;
|
||||
AbstractResourcePoolEntry f = (AbstractResourcePoolEntry) other;
|
||||
return f.path.equals(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getPath();
|
||||
return path();
|
||||
}
|
||||
}
|
@ -29,28 +29,28 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.Objects;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
|
||||
/**
|
||||
* A ModuleEntry backed by a given Archive Entry.
|
||||
* A ResourcePoolEntry backed by a given Archive Entry.
|
||||
*/
|
||||
final class ArchiveEntryModuleEntry extends AbstractModuleEntry {
|
||||
final class ArchiveEntryResourcePoolEntry extends AbstractResourcePoolEntry {
|
||||
private final Archive.Entry entry;
|
||||
|
||||
/**
|
||||
* Create a new ArchiveModuleEntry.
|
||||
* Create a new ArchiveResourcePoolEntry.
|
||||
*
|
||||
* @param module The module name.
|
||||
* @param path The data path identifier.
|
||||
* @param entry The archive Entry.
|
||||
*/
|
||||
ArchiveEntryModuleEntry(String module, String path, Archive.Entry entry) {
|
||||
ArchiveEntryResourcePoolEntry(String module, String path, Archive.Entry entry) {
|
||||
super(module, path, getImageFileType(Objects.requireNonNull(entry)));
|
||||
this.entry = entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream stream() {
|
||||
public InputStream content() {
|
||||
try {
|
||||
return entry.stream();
|
||||
} catch (IOException ex) {
|
||||
@ -59,22 +59,22 @@ final class ArchiveEntryModuleEntry extends AbstractModuleEntry {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength() {
|
||||
public long contentLength() {
|
||||
return entry.size();
|
||||
}
|
||||
|
||||
private static ModuleEntry.Type getImageFileType(Archive.Entry entry) {
|
||||
private static ResourcePoolEntry.Type getImageFileType(Archive.Entry entry) {
|
||||
switch(entry.type()) {
|
||||
case CLASS_OR_RESOURCE:
|
||||
return ModuleEntry.Type.CLASS_OR_RESOURCE;
|
||||
return ResourcePoolEntry.Type.CLASS_OR_RESOURCE;
|
||||
case CONFIG:
|
||||
return ModuleEntry.Type.CONFIG;
|
||||
return ResourcePoolEntry.Type.CONFIG;
|
||||
case NATIVE_CMD:
|
||||
return ModuleEntry.Type.NATIVE_CMD;
|
||||
return ResourcePoolEntry.Type.NATIVE_CMD;
|
||||
case NATIVE_LIB:
|
||||
return ModuleEntry.Type.NATIVE_LIB;
|
||||
return ResourcePoolEntry.Type.NATIVE_LIB;
|
||||
default:
|
||||
return ModuleEntry.Type.OTHER;
|
||||
return ResourcePoolEntry.Type.OTHER;
|
||||
}
|
||||
}
|
||||
}
|
@ -33,31 +33,31 @@ import java.io.UncheckedIOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A ModuleEntry backed by a given byte[].
|
||||
* A ResourcePoolEntry backed by a given byte[].
|
||||
*/
|
||||
class ByteArrayModuleEntry extends AbstractModuleEntry {
|
||||
class ByteArrayResourcePoolEntry extends AbstractResourcePoolEntry {
|
||||
private final byte[] buffer;
|
||||
|
||||
/**
|
||||
* Create a new ByteArrayModuleEntry.
|
||||
* Create a new ByteArrayResourcePoolEntry.
|
||||
*
|
||||
* @param module The module name.
|
||||
* @param path The data path identifier.
|
||||
* @param type The data type.
|
||||
* @param buf The byte buffer.
|
||||
*/
|
||||
ByteArrayModuleEntry(String module, String path, Type type, byte[] buffer) {
|
||||
ByteArrayResourcePoolEntry(String module, String path, Type type, byte[] buffer) {
|
||||
super(module, path, type);
|
||||
this.buffer = Objects.requireNonNull(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
public byte[] contentBytes() {
|
||||
return buffer.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream stream() {
|
||||
public InputStream content() {
|
||||
return new ByteArrayInputStream(buffer);
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ class ByteArrayModuleEntry extends AbstractModuleEntry {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength() {
|
||||
public long contentLength() {
|
||||
return buffer.length;
|
||||
}
|
||||
}
|
@ -42,9 +42,10 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.tools.jlink.internal.Archive.Entry;
|
||||
import jdk.tools.jlink.internal.Archive.Entry.EntryType;
|
||||
import jdk.tools.jlink.internal.ModulePoolImpl.CompressedModuleData;
|
||||
import jdk.tools.jlink.internal.ResourcePoolManager.CompressedModuleData;
|
||||
import jdk.tools.jlink.plugin.PluginException;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
|
||||
/**
|
||||
* An image (native endian.)
|
||||
@ -140,7 +141,7 @@ public final class ImageFileCreator {
|
||||
}));
|
||||
ByteOrder order = ByteOrder.nativeOrder();
|
||||
BasicImageWriter writer = new BasicImageWriter(order);
|
||||
ModulePoolImpl pool = createPools(archives, entriesForModule, order, writer);
|
||||
ResourcePoolManager pool = createPoolManager(archives, entriesForModule, order, writer);
|
||||
try (OutputStream fos = Files.newOutputStream(jimageFile);
|
||||
BufferedOutputStream bos = new BufferedOutputStream(fos);
|
||||
DataOutputStream out = new DataOutputStream(bos)) {
|
||||
@ -158,52 +159,61 @@ public final class ImageFileCreator {
|
||||
ByteOrder byteOrder)
|
||||
throws IOException {
|
||||
BasicImageWriter writer = new BasicImageWriter(byteOrder);
|
||||
ModulePoolImpl allContent = createPools(archives,
|
||||
ResourcePoolManager allContent = createPoolManager(archives,
|
||||
entriesForModule, byteOrder, writer);
|
||||
ModulePoolImpl result = generateJImage(allContent,
|
||||
ResourcePool result = generateJImage(allContent,
|
||||
writer, plugins, plugins.getJImageFileOutputStream());
|
||||
|
||||
//Handle files.
|
||||
try {
|
||||
plugins.storeFiles(allContent, result, writer);
|
||||
plugins.storeFiles(allContent.resourcePool(), result, writer);
|
||||
} catch (Exception ex) {
|
||||
if (JlinkTask.DEBUG) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static ModulePoolImpl generateJImage(ModulePoolImpl allContent,
|
||||
private static ResourcePool generateJImage(ResourcePoolManager allContent,
|
||||
BasicImageWriter writer,
|
||||
ImagePluginStack pluginSupport,
|
||||
DataOutputStream out
|
||||
) throws IOException {
|
||||
ModulePoolImpl resultResources;
|
||||
ResourcePool resultResources;
|
||||
try {
|
||||
resultResources = pluginSupport.visitResources(allContent);
|
||||
} catch (PluginException pe) {
|
||||
if (JlinkTask.DEBUG) {
|
||||
pe.printStackTrace();
|
||||
}
|
||||
throw pe;
|
||||
} catch (Exception ex) {
|
||||
if (JlinkTask.DEBUG) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
throw new IOException(ex);
|
||||
}
|
||||
Set<String> duplicates = new HashSet<>();
|
||||
long[] offset = new long[1];
|
||||
|
||||
List<ModuleEntry> content = new ArrayList<>();
|
||||
List<ResourcePoolEntry> content = new ArrayList<>();
|
||||
List<String> paths = new ArrayList<>();
|
||||
// the order of traversing the resources and the order of
|
||||
// the module content being written must be the same
|
||||
resultResources.entries().forEach(res -> {
|
||||
if (res.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
|
||||
String path = res.getPath();
|
||||
if (res.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
|
||||
String path = res.path();
|
||||
content.add(res);
|
||||
long uncompressedSize = res.getLength();
|
||||
long uncompressedSize = res.contentLength();
|
||||
long compressedSize = 0;
|
||||
if (res instanceof CompressedModuleData) {
|
||||
CompressedModuleData comp
|
||||
= (CompressedModuleData) res;
|
||||
compressedSize = res.getLength();
|
||||
compressedSize = res.contentLength();
|
||||
uncompressedSize = comp.getUncompressedSize();
|
||||
}
|
||||
long onFileSize = res.getLength();
|
||||
long onFileSize = res.contentLength();
|
||||
|
||||
if (duplicates.contains(path)) {
|
||||
System.err.format("duplicate resource \"%s\", skipping%n",
|
||||
@ -239,11 +249,11 @@ public final class ImageFileCreator {
|
||||
return resultResources;
|
||||
}
|
||||
|
||||
private static ModulePoolImpl createPools(Set<Archive> archives,
|
||||
private static ResourcePoolManager createPoolManager(Set<Archive> archives,
|
||||
Map<String, List<Entry>> entriesForModule,
|
||||
ByteOrder byteOrder,
|
||||
BasicImageWriter writer) throws IOException {
|
||||
ModulePoolImpl resources = new ModulePoolImpl(byteOrder, new StringTable() {
|
||||
ResourcePoolManager resources = new ResourcePoolManager(byteOrder, new StringTable() {
|
||||
|
||||
@Override
|
||||
public int addString(String str) {
|
||||
@ -273,7 +283,7 @@ public final class ImageFileCreator {
|
||||
path = "/" + mn + "/" + entry.path();
|
||||
}
|
||||
|
||||
resources.add(new ArchiveEntryModuleEntry(mn, path, entry));
|
||||
resources.add(new ArchiveEntryResourcePoolEntry(mn, path, entry));
|
||||
}
|
||||
}
|
||||
return resources;
|
||||
|
@ -37,7 +37,7 @@ import jdk.tools.jlink.Jlink;
|
||||
import jdk.tools.jlink.plugin.Plugin;
|
||||
import jdk.tools.jlink.plugin.PluginException;
|
||||
import jdk.tools.jlink.plugin.Plugin.Category;
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
|
||||
/**
|
||||
* Plugins configuration.
|
||||
@ -122,7 +122,7 @@ public final class ImagePluginConfiguration {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeFiles(ModulePool files) {
|
||||
public void storeFiles(ResourcePool files) {
|
||||
throw new PluginException("No directory setup to store files");
|
||||
}
|
||||
};
|
||||
|
@ -46,9 +46,10 @@ import jdk.internal.jimage.decompressor.Decompressor;
|
||||
import jdk.tools.jlink.plugin.Plugin;
|
||||
import jdk.tools.jlink.builder.ImageBuilder;
|
||||
import jdk.tools.jlink.plugin.PluginException;
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.plugin.LinkModule;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolModule;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
import jdk.tools.jlink.internal.ResourcePoolManager.ResourcePoolImpl;
|
||||
|
||||
/**
|
||||
* Plugins Stack. Plugins entry point to apply transformations onto resources
|
||||
@ -61,36 +62,47 @@ public final class ImagePluginStack {
|
||||
ExecutableImage retrieve(ImagePluginStack stack) throws IOException;
|
||||
}
|
||||
|
||||
public static final class OrderedResourcePool extends ModulePoolImpl {
|
||||
public static final class OrderedResourcePoolManager extends ResourcePoolManager {
|
||||
class OrderedResourcePool extends ResourcePoolImpl {
|
||||
List<ResourcePoolEntry> getOrderedList() {
|
||||
return OrderedResourcePoolManager.this.getOrderedList();
|
||||
}
|
||||
}
|
||||
|
||||
private final List<ModuleEntry> orderedList = new ArrayList<>();
|
||||
private final List<ResourcePoolEntry> orderedList = new ArrayList<>();
|
||||
private final ResourcePoolImpl poolImpl = new OrderedResourcePool();
|
||||
|
||||
public OrderedResourcePool(ByteOrder order, StringTable table) {
|
||||
public OrderedResourcePoolManager(ByteOrder order, StringTable table) {
|
||||
super(order, table);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourcePool resourcePool() {
|
||||
return poolImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a resource.
|
||||
*
|
||||
* @param resource The Resource to add.
|
||||
*/
|
||||
@Override
|
||||
public void add(ModuleEntry resource) {
|
||||
public void add(ResourcePoolEntry resource) {
|
||||
super.add(resource);
|
||||
orderedList.add(resource);
|
||||
}
|
||||
|
||||
List<ModuleEntry> getOrderedList() {
|
||||
List<ResourcePoolEntry> getOrderedList() {
|
||||
return Collections.unmodifiableList(orderedList);
|
||||
}
|
||||
}
|
||||
|
||||
private final static class CheckOrderResourcePool extends ModulePoolImpl {
|
||||
private final static class CheckOrderResourcePoolManager extends ResourcePoolManager {
|
||||
|
||||
private final List<ModuleEntry> orderedList;
|
||||
private final List<ResourcePoolEntry> orderedList;
|
||||
private int currentIndex;
|
||||
|
||||
public CheckOrderResourcePool(ByteOrder order, List<ModuleEntry> orderedList, StringTable table) {
|
||||
public CheckOrderResourcePoolManager(ByteOrder order, List<ResourcePoolEntry> orderedList, StringTable table) {
|
||||
super(order, table);
|
||||
this.orderedList = Objects.requireNonNull(orderedList);
|
||||
}
|
||||
@ -101,10 +113,10 @@ public final class ImagePluginStack {
|
||||
* @param resource The Resource to add.
|
||||
*/
|
||||
@Override
|
||||
public void add(ModuleEntry resource) {
|
||||
ModuleEntry ordered = orderedList.get(currentIndex);
|
||||
public void add(ResourcePoolEntry resource) {
|
||||
ResourcePoolEntry ordered = orderedList.get(currentIndex);
|
||||
if (!resource.equals(ordered)) {
|
||||
throw new PluginException("Resource " + resource.getPath() + " not in the right order");
|
||||
throw new PluginException("Resource " + resource.path() + " not in the right order");
|
||||
}
|
||||
super.add(resource);
|
||||
currentIndex += 1;
|
||||
@ -209,17 +221,16 @@ public final class ImagePluginStack {
|
||||
* @return The result of the visit.
|
||||
* @throws IOException
|
||||
*/
|
||||
public ModulePoolImpl visitResources(ModulePoolImpl resources)
|
||||
public ResourcePool visitResources(ResourcePoolManager resources)
|
||||
throws Exception {
|
||||
Objects.requireNonNull(resources);
|
||||
resources.setReadOnly();
|
||||
if (resources.isEmpty()) {
|
||||
return new ModulePoolImpl(resources.getByteOrder(),
|
||||
resources.getStringTable());
|
||||
return new ResourcePoolManager(resources.byteOrder(),
|
||||
resources.getStringTable()).resourcePool();
|
||||
}
|
||||
PreVisitStrings previsit = new PreVisitStrings();
|
||||
resourcePrevisitors.stream().forEach((p) -> {
|
||||
p.previsit(resources, previsit);
|
||||
p.previsit(resources.resourcePool(), previsit);
|
||||
});
|
||||
|
||||
// Store the strings resulting from the previsit.
|
||||
@ -228,89 +239,80 @@ public final class ImagePluginStack {
|
||||
resources.getStringTable().addString(s);
|
||||
});
|
||||
|
||||
ModulePoolImpl current = resources;
|
||||
List<ModuleEntry> frozenOrder = null;
|
||||
ResourcePool resPool = resources.resourcePool();
|
||||
List<ResourcePoolEntry> frozenOrder = null;
|
||||
for (Plugin p : plugins) {
|
||||
current.setReadOnly();
|
||||
ModulePoolImpl output = null;
|
||||
ResourcePoolManager resMgr = null;
|
||||
if (p == lastSorter) {
|
||||
if (frozenOrder != null) {
|
||||
throw new Exception("Order of resources is already frozen. Plugin "
|
||||
+ p.getName() + " is badly located");
|
||||
}
|
||||
// Create a special Resource pool to compute the indexes.
|
||||
output = new OrderedResourcePool(current.getByteOrder(),
|
||||
resMgr = new OrderedResourcePoolManager(resPool.byteOrder(),
|
||||
resources.getStringTable());
|
||||
} else {// If we have an order, inject it
|
||||
if (frozenOrder != null) {
|
||||
output = new CheckOrderResourcePool(current.getByteOrder(),
|
||||
resMgr = new CheckOrderResourcePoolManager(resPool.byteOrder(),
|
||||
frozenOrder, resources.getStringTable());
|
||||
} else {
|
||||
output = new ModulePoolImpl(current.getByteOrder(),
|
||||
resMgr = new ResourcePoolManager(resPool.byteOrder(),
|
||||
resources.getStringTable());
|
||||
}
|
||||
}
|
||||
p.visit(current, output);
|
||||
if (output.isEmpty()) {
|
||||
resPool = p.transform(resPool, resMgr.resourcePoolBuilder());
|
||||
if (resPool.isEmpty()) {
|
||||
throw new Exception("Invalid resource pool for plugin " + p);
|
||||
}
|
||||
if (output instanceof OrderedResourcePool) {
|
||||
frozenOrder = ((OrderedResourcePool) output).getOrderedList();
|
||||
if (resPool instanceof OrderedResourcePoolManager.OrderedResourcePool) {
|
||||
frozenOrder = ((OrderedResourcePoolManager.OrderedResourcePool)resPool).getOrderedList();
|
||||
}
|
||||
|
||||
current = output;
|
||||
}
|
||||
current.setReadOnly();
|
||||
return current;
|
||||
return resPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* This pool wrap the original pool and automatically uncompress ModuleEntry
|
||||
* This pool wrap the original pool and automatically uncompress ResourcePoolEntry
|
||||
* if needed.
|
||||
*/
|
||||
private class LastPool implements ModulePool {
|
||||
private class LastModule implements LinkModule {
|
||||
private class LastPoolManager extends ResourcePoolManager {
|
||||
private class LastModule implements ResourcePoolModule {
|
||||
|
||||
final LinkModule module;
|
||||
final ResourcePoolModule module;
|
||||
|
||||
LastModule(LinkModule module) {
|
||||
LastModule(ResourcePoolModule module) {
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return module.getName();
|
||||
public String name() {
|
||||
return module.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ModuleEntry> findEntry(String path) {
|
||||
Optional<ModuleEntry> d = module.findEntry(path);
|
||||
public Optional<ResourcePoolEntry> findEntry(String path) {
|
||||
Optional<ResourcePoolEntry> d = module.findEntry(path);
|
||||
return d.isPresent()? Optional.of(getUncompressed(d.get())) : Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleDescriptor getDescriptor() {
|
||||
return module.getDescriptor();
|
||||
public ModuleDescriptor descriptor() {
|
||||
return module.descriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(ModuleEntry data) {
|
||||
throw new PluginException("pool is readonly");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAllPackages() {
|
||||
return module.getAllPackages();
|
||||
public Set<String> packages() {
|
||||
return module.packages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<ModuleEntry> entries() {
|
||||
List<ModuleEntry> lst = new ArrayList<>();
|
||||
public Stream<ResourcePoolEntry> entries() {
|
||||
List<ResourcePoolEntry> lst = new ArrayList<>();
|
||||
module.entries().forEach(md -> {
|
||||
lst.add(getUncompressed(md));
|
||||
});
|
||||
@ -318,31 +320,27 @@ public final class ImagePluginStack {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntryCount() {
|
||||
return module.getEntryCount();
|
||||
public int entryCount() {
|
||||
return module.entryCount();
|
||||
}
|
||||
}
|
||||
private final ModulePoolImpl pool;
|
||||
Decompressor decompressor = new Decompressor();
|
||||
Collection<ModuleEntry> content;
|
||||
|
||||
LastPool(ModulePoolImpl pool) {
|
||||
private final ResourcePool pool;
|
||||
Decompressor decompressor = new Decompressor();
|
||||
Collection<ResourcePoolEntry> content;
|
||||
|
||||
LastPoolManager(ResourcePool pool) {
|
||||
this.pool = pool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(ModuleEntry resource) {
|
||||
public void add(ResourcePoolEntry resource) {
|
||||
throw new PluginException("pool is readonly");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<LinkModule> findModule(String name) {
|
||||
Optional<LinkModule> module = pool.findModule(name);
|
||||
public Optional<ResourcePoolModule> findModule(String name) {
|
||||
Optional<ResourcePoolModule> module = pool.moduleView().findModule(name);
|
||||
return module.isPresent()? Optional.of(new LastModule(module.get())) : Optional.empty();
|
||||
}
|
||||
|
||||
@ -352,17 +350,17 @@ public final class ImagePluginStack {
|
||||
* @return The collection of modules.
|
||||
*/
|
||||
@Override
|
||||
public Stream<? extends LinkModule> modules() {
|
||||
List<LinkModule> modules = new ArrayList<>();
|
||||
pool.modules().forEach(m -> {
|
||||
public Stream<ResourcePoolModule> modules() {
|
||||
List<ResourcePoolModule> modules = new ArrayList<>();
|
||||
pool.moduleView().modules().forEach(m -> {
|
||||
modules.add(new LastModule(m));
|
||||
});
|
||||
return modules.stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getModuleCount() {
|
||||
return pool.getModuleCount();
|
||||
public int moduleCount() {
|
||||
return pool.moduleView().moduleCount();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -371,7 +369,7 @@ public final class ImagePluginStack {
|
||||
* @return The stream of resources;
|
||||
*/
|
||||
@Override
|
||||
public Stream<? extends ModuleEntry> entries() {
|
||||
public Stream<ResourcePoolEntry> entries() {
|
||||
if (content == null) {
|
||||
content = new ArrayList<>();
|
||||
pool.entries().forEach(md -> {
|
||||
@ -382,8 +380,8 @@ public final class ImagePluginStack {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntryCount() {
|
||||
return pool.getEntryCount();
|
||||
public int entryCount() {
|
||||
return pool.entryCount();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -393,22 +391,22 @@ public final class ImagePluginStack {
|
||||
* @return A Resource instance if the resource is found
|
||||
*/
|
||||
@Override
|
||||
public Optional<ModuleEntry> findEntry(String path) {
|
||||
public Optional<ResourcePoolEntry> findEntry(String path) {
|
||||
Objects.requireNonNull(path);
|
||||
Optional<ModuleEntry> res = pool.findEntry(path);
|
||||
Optional<ResourcePoolEntry> res = pool.findEntry(path);
|
||||
return res.isPresent()? Optional.of(getUncompressed(res.get())) : Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ModuleEntry> findEntryInContext(String path, ModuleEntry context) {
|
||||
public Optional<ResourcePoolEntry> findEntryInContext(String path, ResourcePoolEntry context) {
|
||||
Objects.requireNonNull(path);
|
||||
Objects.requireNonNull(context);
|
||||
Optional<ModuleEntry> res = pool.findEntryInContext(path, context);
|
||||
Optional<ResourcePoolEntry> res = pool.findEntryInContext(path, context);
|
||||
return res.map(this::getUncompressed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(ModuleEntry res) {
|
||||
public boolean contains(ResourcePoolEntry res) {
|
||||
return pool.contains(res);
|
||||
}
|
||||
|
||||
@ -418,29 +416,27 @@ public final class ImagePluginStack {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transformAndCopy(Function<ModuleEntry, ModuleEntry> visitor, ModulePool output) {
|
||||
pool.transformAndCopy(visitor, output);
|
||||
public ByteOrder byteOrder() {
|
||||
return pool.byteOrder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteOrder getByteOrder() {
|
||||
return pool.getByteOrder();
|
||||
public Map<String, String> releaseProperties() {
|
||||
return pool.releaseProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getReleaseProperties() {
|
||||
return Collections.unmodifiableMap(pool.getReleaseProperties());
|
||||
}
|
||||
|
||||
private ModuleEntry getUncompressed(ModuleEntry res) {
|
||||
private ResourcePoolEntry getUncompressed(ResourcePoolEntry res) {
|
||||
if (res != null) {
|
||||
if (res instanceof ModulePoolImpl.CompressedModuleData) {
|
||||
if (res instanceof ResourcePoolManager.CompressedModuleData) {
|
||||
try {
|
||||
byte[] bytes = decompressor.decompressResource(getByteOrder(),
|
||||
(int offset) -> pool.getStringTable().getString(offset),
|
||||
res.getBytes());
|
||||
res = res.create(bytes);
|
||||
byte[] bytes = decompressor.decompressResource(byteOrder(),
|
||||
(int offset) -> ((ResourcePoolImpl)pool).getStringTable().getString(offset),
|
||||
res.contentBytes());
|
||||
res = res.copyWithContent(bytes);
|
||||
} catch (IOException ex) {
|
||||
if (JlinkTask.DEBUG) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
throw new PluginException(ex);
|
||||
}
|
||||
}
|
||||
@ -457,24 +453,24 @@ public final class ImagePluginStack {
|
||||
* @param writer
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
public void storeFiles(ModulePoolImpl original, ModulePoolImpl transformed,
|
||||
public void storeFiles(ResourcePool original, ResourcePool transformed,
|
||||
BasicImageWriter writer)
|
||||
throws Exception {
|
||||
Objects.requireNonNull(original);
|
||||
Objects.requireNonNull(transformed);
|
||||
Optional<LinkModule> javaBase = transformed.findModule("java.base");
|
||||
Optional<ResourcePoolModule> javaBase = transformed.moduleView().findModule("java.base");
|
||||
javaBase.ifPresent(mod -> {
|
||||
try {
|
||||
Map<String, String> release = transformed.getReleaseProperties();
|
||||
Map<String, String> release = transformed.releaseProperties();
|
||||
// fill release information available from transformed "java.base" module!
|
||||
ModuleDescriptor desc = mod.getDescriptor();
|
||||
ModuleDescriptor desc = mod.descriptor();
|
||||
desc.osName().ifPresent(s -> release.put("OS_NAME", s));
|
||||
desc.osVersion().ifPresent(s -> release.put("OS_VERSION", s));
|
||||
desc.osArch().ifPresent(s -> release.put("OS_ARCH", s));
|
||||
} catch (Exception ignored) {}
|
||||
});
|
||||
|
||||
imageBuilder.storeFiles(new LastPool(transformed));
|
||||
imageBuilder.storeFiles(new LastPoolManager(transformed).resourcePool());
|
||||
}
|
||||
|
||||
public ExecutableImage getExecutableImage() throws IOException {
|
||||
|
@ -61,7 +61,7 @@ import jdk.tools.jlink.plugin.Plugin;
|
||||
* ## Should use jdk.joptsimple some day.
|
||||
*/
|
||||
public class JlinkTask {
|
||||
private static final boolean DEBUG = Boolean.getBoolean("jlink.debug");
|
||||
static final boolean DEBUG = Boolean.getBoolean("jlink.debug");
|
||||
|
||||
private static <T extends Throwable> void fail(Class<T> type,
|
||||
String format,
|
||||
|
@ -33,20 +33,20 @@ import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A ModuleEntry backed by a given nio Path.
|
||||
* A ResourcePoolEntry backed by a given nio Path.
|
||||
*/
|
||||
public class PathModuleEntry extends AbstractModuleEntry {
|
||||
public class PathResourcePoolEntry extends AbstractResourcePoolEntry {
|
||||
private final Path file;
|
||||
|
||||
/**
|
||||
* Create a new PathModuleEntry.
|
||||
* Create a new PathResourcePoolEntry.
|
||||
*
|
||||
* @param module The module name.
|
||||
* @param path The path for the resource content.
|
||||
* @param type The data type.
|
||||
* @param file The data file identifier.
|
||||
*/
|
||||
public PathModuleEntry(String module, String path, Type type, Path file) {
|
||||
public PathResourcePoolEntry(String module, String path, Type type, Path file) {
|
||||
super(module, path, type);
|
||||
this.file = Objects.requireNonNull(file);
|
||||
if (!Files.isRegularFile(file)) {
|
||||
@ -55,7 +55,7 @@ public class PathModuleEntry extends AbstractModuleEntry {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final InputStream stream() {
|
||||
public final InputStream content() {
|
||||
try {
|
||||
return Files.newInputStream(file);
|
||||
} catch (IOException ex) {
|
||||
@ -64,7 +64,7 @@ public class PathModuleEntry extends AbstractModuleEntry {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final long getLength() {
|
||||
public final long contentLength() {
|
||||
try {
|
||||
return Files.size(file);
|
||||
} catch (IOException ex) {
|
@ -26,57 +26,41 @@ package jdk.tools.jlink.internal;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
|
||||
public final class ModuleEntryFactory {
|
||||
private ModuleEntryFactory() {}
|
||||
public final class ResourcePoolEntryFactory {
|
||||
private ResourcePoolEntryFactory() {}
|
||||
|
||||
public static ModuleEntry create(String path,
|
||||
ModuleEntry.Type type, byte[] content) {
|
||||
return new ByteArrayModuleEntry(moduleFrom(path), path, type, content);
|
||||
public static ResourcePoolEntry create(String path,
|
||||
ResourcePoolEntry.Type type, byte[] content) {
|
||||
return new ByteArrayResourcePoolEntry(moduleFrom(path), path, type, content);
|
||||
}
|
||||
|
||||
public static ModuleEntry create(String path,
|
||||
ModuleEntry.Type type, Path file) {
|
||||
return new PathModuleEntry(moduleFrom(path), path, type, file);
|
||||
public static ResourcePoolEntry create(String path,
|
||||
ResourcePoolEntry.Type type, Path file) {
|
||||
return new PathResourcePoolEntry(moduleFrom(path), path, type, file);
|
||||
}
|
||||
|
||||
public static ModuleEntry create(ModuleEntry original, byte[] content) {
|
||||
return new ByteArrayModuleEntry(original.getModule(),
|
||||
original.getPath(), original.getType(), content);
|
||||
public static ResourcePoolEntry create(ResourcePoolEntry original, byte[] content) {
|
||||
return new ByteArrayResourcePoolEntry(original.moduleName(),
|
||||
original.path(), original.type(), content);
|
||||
}
|
||||
|
||||
public static ModuleEntry create(ModuleEntry original, Path file) {
|
||||
return new PathModuleEntry(original.getModule(),
|
||||
original.getPath(), original.getType(), file);
|
||||
public static ResourcePoolEntry create(ResourcePoolEntry original, Path file) {
|
||||
return new PathResourcePoolEntry(original.moduleName(),
|
||||
original.path(), original.type(), file);
|
||||
}
|
||||
|
||||
static String moduleFrom(String path) {
|
||||
private static String moduleFrom(String path) {
|
||||
Objects.requireNonNull(path);
|
||||
if (path.isEmpty() || path.charAt(0) != '/') {
|
||||
throw new IllegalArgumentException(path + " must start with /");
|
||||
}
|
||||
int idx = path.indexOf('/', 1);
|
||||
String noRoot = path.substring(1);
|
||||
int idx = noRoot.indexOf('/');
|
||||
if (idx == -1) {
|
||||
throw new IllegalArgumentException("/ missing after module: " + path);
|
||||
}
|
||||
return path.substring(1, idx);
|
||||
}
|
||||
|
||||
static String packageFrom(String path) {
|
||||
Objects.requireNonNull(path);
|
||||
int idx = path.lastIndexOf('/');
|
||||
if (idx == -1) {
|
||||
throw new IllegalArgumentException("/ missing from path: " + path);
|
||||
}
|
||||
if (path.startsWith("/")) {
|
||||
int jdx = path.indexOf('/', 1);
|
||||
if (jdx == -1) {
|
||||
throw new IllegalArgumentException("/ missing after module: " + path);
|
||||
}
|
||||
return path.substring(jdx + 1, idx);
|
||||
} else {
|
||||
return path.substring(0, idx);
|
||||
}
|
||||
return noRoot.substring(0, idx);
|
||||
}
|
||||
}
|
@ -38,34 +38,36 @@ import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.internal.jimage.decompressor.CompressedResourceHeader;
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.plugin.LinkModule;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolModule;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolModuleView;
|
||||
import jdk.tools.jlink.plugin.PluginException;
|
||||
import jdk.tools.jlink.internal.plugins.FileCopierPlugin;
|
||||
|
||||
/**
|
||||
* Pool of module data.
|
||||
* A manager for pool of resources.
|
||||
*/
|
||||
public class ModulePoolImpl implements ModulePool {
|
||||
public class ResourcePoolManager {
|
||||
|
||||
private class ModuleImpl implements LinkModule {
|
||||
class ResourcePoolModuleImpl implements ResourcePoolModule {
|
||||
|
||||
final Map<String, ModuleEntry> moduleContent = new LinkedHashMap<>();
|
||||
final Map<String, ResourcePoolEntry> moduleContent = new LinkedHashMap<>();
|
||||
private ModuleDescriptor descriptor;
|
||||
final String name;
|
||||
|
||||
private ModuleImpl(String name) {
|
||||
private ResourcePoolModuleImpl(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ModuleEntry> findEntry(String path) {
|
||||
public Optional<ResourcePoolEntry> findEntry(String path) {
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
@ -76,41 +78,28 @@ public class ModulePoolImpl implements ModulePool {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleDescriptor getDescriptor() {
|
||||
public ModuleDescriptor descriptor() {
|
||||
if (descriptor == null) {
|
||||
String p = "/" + name + "/module-info.class";
|
||||
Optional<ModuleEntry> content = findEntry(p);
|
||||
Optional<ResourcePoolEntry> content = findEntry(p);
|
||||
if (!content.isPresent()) {
|
||||
throw new PluginException("No module-info for " + name
|
||||
+ " module");
|
||||
}
|
||||
ByteBuffer bb = ByteBuffer.wrap(content.get().getBytes());
|
||||
ByteBuffer bb = ByteBuffer.wrap(content.get().contentBytes());
|
||||
descriptor = ModuleDescriptor.read(bb);
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(ModuleEntry data) {
|
||||
if (isReadOnly()) {
|
||||
throw new PluginException("ModulePool is readonly");
|
||||
}
|
||||
Objects.requireNonNull(data);
|
||||
if (!data.getModule().equals(name)) {
|
||||
throw new PluginException("Can't add resource " + data.getPath()
|
||||
+ " to module " + name);
|
||||
}
|
||||
ModulePoolImpl.this.add(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAllPackages() {
|
||||
public Set<String> packages() {
|
||||
Set<String> pkgs = new HashSet<>();
|
||||
moduleContent.values().stream().filter(m -> m.getType().
|
||||
equals(ModuleEntry.Type.CLASS_OR_RESOURCE)).forEach(res -> {
|
||||
moduleContent.values().stream().filter(m -> m.type().
|
||||
equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)).forEach(res -> {
|
||||
// Module metadata only contains packages with .class files
|
||||
if (ImageFileCreator.isClassPackage(res.getPath())) {
|
||||
String[] split = ImageFileCreator.splitPath(res.getPath());
|
||||
if (ImageFileCreator.isClassPackage(res.path())) {
|
||||
String[] split = ImageFileCreator.splitPath(res.path());
|
||||
String pkg = split[1];
|
||||
if (pkg != null && !pkg.isEmpty()) {
|
||||
pkgs.add(pkg);
|
||||
@ -122,35 +111,121 @@ public class ModulePoolImpl implements ModulePool {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<? extends ModuleEntry> entries() {
|
||||
public Stream<ResourcePoolEntry> entries() {
|
||||
return moduleContent.values().stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntryCount() {
|
||||
public int entryCount() {
|
||||
return moduleContent.values().size();
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<String, ModuleEntry> resources = new LinkedHashMap<>();
|
||||
private final Map<String, ModuleImpl> modules = new LinkedHashMap<>();
|
||||
private final ModuleImpl fileCopierModule = new ModuleImpl(FileCopierPlugin.FAKE_MODULE);
|
||||
public class ResourcePoolImpl implements ResourcePool {
|
||||
@Override
|
||||
public ResourcePoolModuleView moduleView() {
|
||||
return ResourcePoolManager.this.moduleView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<ResourcePoolEntry> entries() {
|
||||
return ResourcePoolManager.this.entries();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int entryCount() {
|
||||
return ResourcePoolManager.this.entryCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ResourcePoolEntry> findEntry(String path) {
|
||||
return ResourcePoolManager.this.findEntry(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ResourcePoolEntry> findEntryInContext(String path, ResourcePoolEntry context) {
|
||||
return ResourcePoolManager.this.findEntryInContext(path, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(ResourcePoolEntry data) {
|
||||
return ResourcePoolManager.this.contains(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return ResourcePoolManager.this.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteOrder byteOrder() {
|
||||
return ResourcePoolManager.this.byteOrder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> releaseProperties() {
|
||||
return ResourcePoolManager.this.releaseProperties();
|
||||
}
|
||||
|
||||
public StringTable getStringTable() {
|
||||
return ResourcePoolManager.this.getStringTable();
|
||||
}
|
||||
}
|
||||
|
||||
class ResourcePoolBuilderImpl implements ResourcePoolBuilder {
|
||||
private boolean built;
|
||||
|
||||
@Override
|
||||
public void add(ResourcePoolEntry data) {
|
||||
if (built) {
|
||||
throw new IllegalStateException("resource pool already built!");
|
||||
}
|
||||
ResourcePoolManager.this.add(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourcePool build() {
|
||||
built = true;
|
||||
return ResourcePoolManager.this.resourcePool();
|
||||
}
|
||||
}
|
||||
|
||||
class ResourcePoolModuleViewImpl implements ResourcePoolModuleView {
|
||||
@Override
|
||||
public Optional<ResourcePoolModule> findModule(String name) {
|
||||
return ResourcePoolManager.this.findModule(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<ResourcePoolModule> modules() {
|
||||
return ResourcePoolManager.this.modules();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int moduleCount() {
|
||||
return ResourcePoolManager.this.moduleCount();
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<String, ResourcePoolEntry> resources = new LinkedHashMap<>();
|
||||
private final Map<String, ResourcePoolModule> modules = new LinkedHashMap<>();
|
||||
private final ResourcePoolModuleImpl fileCopierModule = new ResourcePoolModuleImpl(FileCopierPlugin.FAKE_MODULE);
|
||||
private Map<String, String> releaseProps = new HashMap<>();
|
||||
|
||||
private final ByteOrder order;
|
||||
|
||||
private boolean isReadOnly;
|
||||
private final StringTable table;
|
||||
private final ResourcePool poolImpl;
|
||||
private final ResourcePoolBuilder poolBuilderImpl;
|
||||
private final ResourcePoolModuleView moduleViewImpl;
|
||||
|
||||
public ModulePoolImpl() {
|
||||
public ResourcePoolManager() {
|
||||
this(ByteOrder.nativeOrder());
|
||||
}
|
||||
|
||||
public ModulePoolImpl(ByteOrder order) {
|
||||
public ResourcePoolManager(ByteOrder order) {
|
||||
this(order, new StringTable() {
|
||||
|
||||
@Override
|
||||
@ -165,39 +240,50 @@ public class ModulePoolImpl implements ModulePool {
|
||||
});
|
||||
}
|
||||
|
||||
public ModulePoolImpl(ByteOrder order, StringTable table) {
|
||||
public ResourcePoolManager(ByteOrder order, StringTable table) {
|
||||
this.order = Objects.requireNonNull(order);
|
||||
this.table = Objects.requireNonNull(table);
|
||||
this.poolImpl = new ResourcePoolImpl();
|
||||
this.poolBuilderImpl = new ResourcePoolBuilderImpl();
|
||||
this.moduleViewImpl = new ResourcePoolModuleViewImpl();
|
||||
}
|
||||
|
||||
public ResourcePool resourcePool() {
|
||||
return poolImpl;
|
||||
}
|
||||
|
||||
public ResourcePoolBuilder resourcePoolBuilder() {
|
||||
return poolBuilderImpl;
|
||||
}
|
||||
|
||||
public ResourcePoolModuleView moduleView() {
|
||||
return moduleViewImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a ModuleEntry.
|
||||
* Add a ResourcePoolEntry.
|
||||
*
|
||||
* @param data The ModuleEntry to add.
|
||||
* @param data The ResourcePoolEntry to add.
|
||||
*/
|
||||
@Override
|
||||
public void add(ModuleEntry data) {
|
||||
if (isReadOnly()) {
|
||||
throw new PluginException("ModulePool is readonly");
|
||||
}
|
||||
public void add(ResourcePoolEntry data) {
|
||||
Objects.requireNonNull(data);
|
||||
if (resources.get(data.getPath()) != null) {
|
||||
throw new PluginException("Resource " + data.getPath()
|
||||
if (resources.get(data.path()) != null) {
|
||||
throw new PluginException("Resource " + data.path()
|
||||
+ " already present");
|
||||
}
|
||||
String modulename = data.getModule();
|
||||
ModuleImpl m = modules.get(modulename);
|
||||
String modulename = data.moduleName();
|
||||
ResourcePoolModuleImpl m = (ResourcePoolModuleImpl)modules.get(modulename);
|
||||
// ## TODO: FileCopierPlugin should not add content to a module
|
||||
// FAKE_MODULE is not really a module to be added in the image
|
||||
if (FileCopierPlugin.FAKE_MODULE.equals(modulename)) {
|
||||
m = fileCopierModule;
|
||||
}
|
||||
if (m == null) {
|
||||
m = new ModuleImpl(modulename);
|
||||
m = new ResourcePoolModuleImpl(modulename);
|
||||
modules.put(modulename, m);
|
||||
}
|
||||
resources.put(data.getPath(), data);
|
||||
m.moduleContent.put(data.getPath(), data);
|
||||
resources.put(data.path(), data);
|
||||
m.moduleContent.put(data.path(), data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -206,175 +292,123 @@ public class ModulePoolImpl implements ModulePool {
|
||||
* @param name The module name
|
||||
* @return the module of matching name, if found
|
||||
*/
|
||||
@Override
|
||||
public Optional<LinkModule> findModule(String name) {
|
||||
public Optional<ResourcePoolModule> findModule(String name) {
|
||||
Objects.requireNonNull(name);
|
||||
return Optional.ofNullable(modules.get(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* The stream of modules contained in this ModulePool.
|
||||
* The stream of modules contained in this ResourcePool.
|
||||
*
|
||||
* @return The stream of modules.
|
||||
*/
|
||||
@Override
|
||||
public Stream<? extends LinkModule> modules() {
|
||||
public Stream<ResourcePoolModule> modules() {
|
||||
return modules.values().stream();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of LinkModule count in this ModulePool.
|
||||
* Return the number of ResourcePoolModule count in this ResourcePool.
|
||||
*
|
||||
* @return the module count.
|
||||
*/
|
||||
@Override
|
||||
public int getModuleCount() {
|
||||
public int moduleCount() {
|
||||
return modules.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all ModuleEntry contained in this ModulePool instance.
|
||||
* Get all ResourcePoolEntry contained in this ResourcePool instance.
|
||||
*
|
||||
* @return The stream of LinkModuleEntries.
|
||||
* @return The stream of ResourcePoolModuleEntries.
|
||||
*/
|
||||
@Override
|
||||
public Stream<? extends ModuleEntry> entries() {
|
||||
public Stream<ResourcePoolEntry> entries() {
|
||||
return resources.values().stream();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of ModuleEntry count in this ModulePool.
|
||||
* Return the number of ResourcePoolEntry count in this ResourcePool.
|
||||
*
|
||||
* @return the entry count.
|
||||
*/
|
||||
@Override
|
||||
public int getEntryCount() {
|
||||
public int entryCount() {
|
||||
return resources.values().size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ModuleEntry for the passed path.
|
||||
* Get the ResourcePoolEntry for the passed path.
|
||||
*
|
||||
* @param path A data path
|
||||
* @return A ModuleEntry instance or null if the data is not found
|
||||
* @return A ResourcePoolEntry instance or null if the data is not found
|
||||
*/
|
||||
@Override
|
||||
public Optional<ModuleEntry> findEntry(String path) {
|
||||
public Optional<ResourcePoolEntry> findEntry(String path) {
|
||||
Objects.requireNonNull(path);
|
||||
return Optional.ofNullable(resources.get(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ModuleEntry for the passed path restricted to supplied context.
|
||||
* Get the ResourcePoolEntry for the passed path restricted to supplied context.
|
||||
*
|
||||
* @param path A data path
|
||||
* @param context A context of the search
|
||||
* @return A ModuleEntry instance or null if the data is not found
|
||||
* @return A ResourcePoolEntry instance or null if the data is not found
|
||||
*/
|
||||
@Override
|
||||
public Optional<ModuleEntry> findEntryInContext(String path, ModuleEntry context) {
|
||||
public Optional<ResourcePoolEntry> findEntryInContext(String path, ResourcePoolEntry context) {
|
||||
Objects.requireNonNull(path);
|
||||
Objects.requireNonNull(context);
|
||||
LinkModule module = modules.get(context.getModule());
|
||||
ResourcePoolModule module = modules.get(context.moduleName());
|
||||
Objects.requireNonNull(module);
|
||||
Optional<ModuleEntry> entry = module.findEntry(path);
|
||||
Optional<ResourcePoolEntry> entry = module.findEntry(path);
|
||||
// Navigating other modules via requires and exports is problematic
|
||||
// since we cannot construct the runtime model of loaders and layers.
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the ModulePool contains the given ModuleEntry.
|
||||
* Check if the ResourcePool contains the given ResourcePoolEntry.
|
||||
*
|
||||
* @param data The module data to check existence for.
|
||||
* @return The module data or null if not found.
|
||||
*/
|
||||
@Override
|
||||
public boolean contains(ModuleEntry data) {
|
||||
public boolean contains(ResourcePoolEntry data) {
|
||||
Objects.requireNonNull(data);
|
||||
return findEntry(data.getPath()).isPresent();
|
||||
return findEntry(data.path()).isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the ModulePool contains some content at all.
|
||||
* Check if the ResourcePool contains some content at all.
|
||||
*
|
||||
* @return True, no content, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return resources.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit each ModuleEntry in this ModulePool to transform it and
|
||||
* copy the transformed ModuleEntry to the output ModulePool.
|
||||
*
|
||||
* @param transform The function called for each ModuleEntry found in
|
||||
* the ModulePool. The transform function should return a
|
||||
* ModuleEntry instance which will be added to the output or it should
|
||||
* return null if the passed ModuleEntry is to be ignored for the
|
||||
* output.
|
||||
*
|
||||
* @param output The ModulePool to be filled with Visitor returned
|
||||
* ModuleEntry.
|
||||
*/
|
||||
@Override
|
||||
public void transformAndCopy(Function<ModuleEntry, ModuleEntry> transform,
|
||||
ModulePool output) {
|
||||
entries().forEach(resource -> {
|
||||
ModuleEntry res = transform.apply(resource);
|
||||
if (res != null) {
|
||||
output.add(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The ByteOrder currently in use when generating the jimage file.
|
||||
*
|
||||
* @return The ByteOrder.
|
||||
*/
|
||||
@Override
|
||||
public ByteOrder getByteOrder() {
|
||||
public ByteOrder byteOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getReleaseProperties() {
|
||||
return isReadOnly()? Collections.unmodifiableMap(releaseProps) : releaseProps;
|
||||
public Map<String, String> releaseProperties() {
|
||||
return releaseProps;
|
||||
}
|
||||
|
||||
public StringTable getStringTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make this Resources instance read-only. No resource can be added.
|
||||
*/
|
||||
public void setReadOnly() {
|
||||
isReadOnly = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read only state.
|
||||
*
|
||||
* @return true if readonly false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return isReadOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* A resource that has been compressed.
|
||||
*/
|
||||
public static final class CompressedModuleData extends ByteArrayModuleEntry {
|
||||
public static final class CompressedModuleData extends ByteArrayResourcePoolEntry {
|
||||
|
||||
final long uncompressed_size;
|
||||
|
||||
private CompressedModuleData(String module, String path,
|
||||
byte[] content, long uncompressed_size) {
|
||||
super(module, path, ModuleEntry.Type.CLASS_OR_RESOURCE, content);
|
||||
super(module, path, ResourcePoolEntry.Type.CLASS_OR_RESOURCE, content);
|
||||
this.uncompressed_size = uncompressed_size;
|
||||
}
|
||||
|
||||
@ -388,7 +422,7 @@ public class ModulePoolImpl implements ModulePool {
|
||||
return false;
|
||||
}
|
||||
CompressedModuleData f = (CompressedModuleData) other;
|
||||
return f.getPath().equals(getPath());
|
||||
return f.path().equals(path());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -397,7 +431,7 @@ public class ModulePoolImpl implements ModulePool {
|
||||
}
|
||||
}
|
||||
|
||||
public static CompressedModuleData newCompressedResource(ModuleEntry original,
|
||||
public static CompressedModuleData newCompressedResource(ResourcePoolEntry original,
|
||||
ByteBuffer compressed,
|
||||
String plugin, String pluginConfig, StringTable strings,
|
||||
ByteOrder order) {
|
||||
@ -406,7 +440,7 @@ public class ModulePoolImpl implements ModulePool {
|
||||
Objects.requireNonNull(plugin);
|
||||
|
||||
boolean isTerminal = !(original instanceof CompressedModuleData);
|
||||
long uncompressed_size = original.getLength();
|
||||
long uncompressed_size = original.contentLength();
|
||||
if (original instanceof CompressedModuleData) {
|
||||
CompressedModuleData comp = (CompressedModuleData) original;
|
||||
uncompressed_size = comp.getUncompressedSize();
|
||||
@ -417,7 +451,7 @@ public class ModulePoolImpl implements ModulePool {
|
||||
configOffset = strings.addString(plugin);
|
||||
}
|
||||
CompressedResourceHeader rh
|
||||
= new CompressedResourceHeader(compressed.limit(), original.getLength(),
|
||||
= new CompressedResourceHeader(compressed.limit(), original.contentLength(),
|
||||
nameOffset, configOffset, isTerminal);
|
||||
// Merge header with content;
|
||||
byte[] h = rh.getBytes(order);
|
||||
@ -428,9 +462,8 @@ public class ModulePoolImpl implements ModulePool {
|
||||
byte[] contentWithHeader = bb.array();
|
||||
|
||||
CompressedModuleData compressedResource
|
||||
= new CompressedModuleData(original.getModule(), original.getPath(),
|
||||
= new CompressedModuleData(original.moduleName(), original.path(),
|
||||
contentWithHeader, uncompressed_size);
|
||||
return compressedResource;
|
||||
}
|
||||
|
||||
}
|
@ -24,7 +24,7 @@
|
||||
*/
|
||||
package jdk.tools.jlink.internal;
|
||||
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
|
||||
/**
|
||||
* Plugin wishing to pre-visit the resources must implement this interface.
|
||||
@ -43,5 +43,5 @@ public interface ResourcePrevisitor {
|
||||
* @param strings StringTable instance. Add string to the StringTable to track string
|
||||
* usage.
|
||||
*/
|
||||
public void previsit(ModulePool resources, StringTable strings);
|
||||
public void previsit(ResourcePool resources, StringTable strings);
|
||||
}
|
||||
|
@ -29,7 +29,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
|
||||
import jdk.tools.jlink.plugin.Plugin.Category;
|
||||
import jdk.internal.org.objectweb.asm.ClassReader;
|
||||
import static jdk.internal.org.objectweb.asm.ClassReader.*;
|
||||
@ -44,7 +45,7 @@ import jdk.internal.org.objectweb.asm.tree.LdcInsnNode;
|
||||
import jdk.internal.org.objectweb.asm.tree.LineNumberNode;
|
||||
import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
|
||||
import jdk.internal.org.objectweb.asm.tree.MethodNode;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
import jdk.tools.jlink.plugin.Plugin;
|
||||
|
||||
public final class ClassForNamePlugin implements Plugin {
|
||||
@ -55,8 +56,8 @@ public final class ClassForNamePlugin implements Plugin {
|
||||
path.length() - ".class".length());
|
||||
}
|
||||
|
||||
private static int getAccess(ModuleEntry resource) {
|
||||
ClassReader cr = new ClassReader(resource.getBytes());
|
||||
private static int getAccess(ResourcePoolEntry resource) {
|
||||
ClassReader cr = new ClassReader(resource.contentBytes());
|
||||
|
||||
return cr.getAccess();
|
||||
}
|
||||
@ -67,8 +68,8 @@ public final class ClassForNamePlugin implements Plugin {
|
||||
return index == -1 ? "" : binaryName.substring(0, index);
|
||||
}
|
||||
|
||||
private ModuleEntry transform(ModuleEntry resource, ModulePool pool) {
|
||||
byte[] inBytes = resource.getBytes();
|
||||
private ResourcePoolEntry transform(ResourcePoolEntry resource, ResourcePool pool) {
|
||||
byte[] inBytes = resource.contentBytes();
|
||||
ClassReader cr = new ClassReader(inBytes);
|
||||
ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, EXPAND_FRAMES);
|
||||
@ -76,7 +77,7 @@ public final class ClassForNamePlugin implements Plugin {
|
||||
boolean modified = false;
|
||||
LdcInsnNode ldc = null;
|
||||
|
||||
String thisPackage = getPackage(binaryClassName(resource.getPath()));
|
||||
String thisPackage = getPackage(binaryClassName(resource.path()));
|
||||
|
||||
for (MethodNode mn : ms) {
|
||||
InsnList il = mn.instructions;
|
||||
@ -96,7 +97,7 @@ public final class ClassForNamePlugin implements Plugin {
|
||||
min.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
|
||||
String ldcClassName = ldc.cst.toString();
|
||||
String thatClassName = ldcClassName.replaceAll("\\.", "/");
|
||||
Optional<ModuleEntry> thatClass =
|
||||
Optional<ResourcePoolEntry> thatClass =
|
||||
pool.findEntryInContext(thatClassName + ".class", resource);
|
||||
|
||||
if (thatClass.isPresent()) {
|
||||
@ -128,7 +129,7 @@ public final class ClassForNamePlugin implements Plugin {
|
||||
cn.accept(cw);
|
||||
byte[] outBytes = cw.toByteArray();
|
||||
|
||||
return resource.create(outBytes);
|
||||
return resource.copyWithContent(outBytes);
|
||||
}
|
||||
|
||||
return resource;
|
||||
@ -140,13 +141,13 @@ public final class ClassForNamePlugin implements Plugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ModulePool in, ModulePool out) {
|
||||
public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
|
||||
Objects.requireNonNull(in);
|
||||
Objects.requireNonNull(out);
|
||||
|
||||
in.entries()
|
||||
.forEach(resource -> {
|
||||
String path = resource.getPath();
|
||||
String path = resource.path();
|
||||
|
||||
if (path.endsWith(".class") && !path.endsWith("/module-info.class")) {
|
||||
out.add(transform(resource, in));
|
||||
@ -154,6 +155,7 @@ public final class ClassForNamePlugin implements Plugin {
|
||||
out.add(resource);
|
||||
}
|
||||
});
|
||||
return out.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,10 +26,12 @@ package jdk.tools.jlink.internal.plugins;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.tools.jlink.internal.ModulePoolImpl;
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.internal.ResourcePoolManager.ResourcePoolImpl;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
|
||||
import jdk.tools.jlink.plugin.Plugin;
|
||||
import jdk.tools.jlink.internal.ImagePluginStack;
|
||||
import jdk.tools.jlink.internal.ResourcePoolManager;
|
||||
import jdk.tools.jlink.internal.ResourcePrevisitor;
|
||||
import jdk.tools.jlink.internal.StringTable;
|
||||
|
||||
@ -53,21 +55,22 @@ public final class DefaultCompressPlugin implements Plugin, ResourcePrevisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ModulePool in, ModulePool out) {
|
||||
public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
|
||||
if (ss != null && zip != null) {
|
||||
ModulePool output = new ImagePluginStack.OrderedResourcePool(in.getByteOrder(),
|
||||
((ModulePoolImpl) in).getStringTable());
|
||||
ss.visit(in, output);
|
||||
zip.visit(output, out);
|
||||
ResourcePoolManager resMgr = new ImagePluginStack.OrderedResourcePoolManager(
|
||||
in.byteOrder(), ((ResourcePoolImpl)in).getStringTable());
|
||||
return zip.transform(ss.transform(in, resMgr.resourcePoolBuilder()), out);
|
||||
} else if (ss != null) {
|
||||
ss.visit(in, out);
|
||||
return ss.transform(in, out);
|
||||
} else if (zip != null) {
|
||||
zip.visit(in, out);
|
||||
return zip.transform(in, out);
|
||||
}
|
||||
|
||||
return out.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void previsit(ModulePool resources, StringTable strings) {
|
||||
public void previsit(ResourcePool resources, StringTable strings) {
|
||||
if (ss != null) {
|
||||
ss.previsit(resources, strings);
|
||||
}
|
||||
|
@ -27,8 +27,9 @@ package jdk.tools.jlink.internal.plugins;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import jdk.tools.jlink.plugin.Plugin;
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -45,13 +46,14 @@ public final class ExcludeFilesPlugin implements Plugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ModulePool in, ModulePool out) {
|
||||
public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
|
||||
in.transformAndCopy((file) -> {
|
||||
if (!file.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
|
||||
file = predicate.test(file.getPath()) ? file : null;
|
||||
if (!file.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
|
||||
file = predicate.test(file.path()) ? file : null;
|
||||
}
|
||||
return file;
|
||||
}, out);
|
||||
return out.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -27,8 +27,9 @@ package jdk.tools.jlink.internal.plugins;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import jdk.tools.jlink.plugin.Plugin;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -45,13 +46,14 @@ public final class ExcludePlugin implements Plugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ModulePool in, ModulePool out) {
|
||||
public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
|
||||
in.transformAndCopy((resource) -> {
|
||||
if (resource.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
|
||||
resource = predicate.test(resource.getPath()) ? resource : null;
|
||||
if (resource.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
|
||||
resource = predicate.test(resource.path()) ? resource : null;
|
||||
}
|
||||
return resource;
|
||||
}, out);
|
||||
return out.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -36,8 +36,9 @@ import java.util.TreeSet;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import jdk.tools.jlink.plugin.Plugin;
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
import jdk.tools.jlink.plugin.PluginException;
|
||||
|
||||
/**
|
||||
@ -97,25 +98,25 @@ public final class ExcludeVMPlugin implements Plugin {
|
||||
* e.g.: /java.base/native/amd64/server/libjvm.so
|
||||
* /java.base/native/server/libjvm.dylib
|
||||
*/
|
||||
private List<ModuleEntry> getVMs(ModulePool in) {
|
||||
private List<ResourcePoolEntry> getVMs(ResourcePool in) {
|
||||
String jvmlib = jvmlib();
|
||||
List<ModuleEntry> ret = in.findModule("java.base").get().entries().filter((t) -> {
|
||||
return t.getPath().endsWith("/" + jvmlib);
|
||||
List<ResourcePoolEntry> ret = in.moduleView().findModule("java.base").get().entries().filter((t) -> {
|
||||
return t.path().endsWith("/" + jvmlib);
|
||||
}).collect(Collectors.toList());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ModulePool in, ModulePool out) {
|
||||
public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
|
||||
String jvmlib = jvmlib();
|
||||
TreeSet<Jvm> existing = new TreeSet<>(new JvmComparator());
|
||||
TreeSet<Jvm> removed = new TreeSet<>(new JvmComparator());
|
||||
if (!keepAll) {
|
||||
// First retrieve all available VM names and removed VM
|
||||
List<ModuleEntry> jvms = getVMs(in);
|
||||
List<ResourcePoolEntry> jvms = getVMs(in);
|
||||
for (Jvm jvm : Jvm.values()) {
|
||||
for (ModuleEntry md : jvms) {
|
||||
if (md.getPath().endsWith("/" + jvm.getName() + "/" + jvmlib)) {
|
||||
for (ResourcePoolEntry md : jvms) {
|
||||
if (md.path().endsWith("/" + jvm.getName() + "/" + jvmlib)) {
|
||||
existing.add(jvm);
|
||||
if (isRemoved(md)) {
|
||||
removed.add(jvm);
|
||||
@ -134,8 +135,8 @@ public final class ExcludeVMPlugin implements Plugin {
|
||||
// Rewrite the jvm.cfg file.
|
||||
in.transformAndCopy((file) -> {
|
||||
if (!keepAll) {
|
||||
if (file.getType().equals(ModuleEntry.Type.NATIVE_LIB)) {
|
||||
if (file.getPath().endsWith(JVM_CFG)) {
|
||||
if (file.type().equals(ResourcePoolEntry.Type.NATIVE_LIB)) {
|
||||
if (file.path().endsWith(JVM_CFG)) {
|
||||
try {
|
||||
file = handleJvmCfgFile(file, existing, removed);
|
||||
} catch (IOException ex) {
|
||||
@ -148,10 +149,11 @@ public final class ExcludeVMPlugin implements Plugin {
|
||||
return file;
|
||||
}, out);
|
||||
|
||||
return out.build();
|
||||
}
|
||||
|
||||
private boolean isRemoved(ModuleEntry file) {
|
||||
return !predicate.test(file.getPath());
|
||||
private boolean isRemoved(ResourcePoolEntry file) {
|
||||
return !predicate.test(file.path());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -206,7 +208,7 @@ public final class ExcludeVMPlugin implements Plugin {
|
||||
predicate = ResourceFilter.excludeFilter(exclude);
|
||||
}
|
||||
|
||||
private ModuleEntry handleJvmCfgFile(ModuleEntry orig,
|
||||
private ResourcePoolEntry handleJvmCfgFile(ResourcePoolEntry orig,
|
||||
TreeSet<Jvm> existing,
|
||||
TreeSet<Jvm> removed) throws IOException {
|
||||
if (keepAll) {
|
||||
@ -215,7 +217,7 @@ public final class ExcludeVMPlugin implements Plugin {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
// Keep comments
|
||||
try (BufferedReader reader
|
||||
= new BufferedReader(new InputStreamReader(orig.stream(),
|
||||
= new BufferedReader(new InputStreamReader(orig.content(),
|
||||
StandardCharsets.UTF_8))) {
|
||||
reader.lines().forEach((s) -> {
|
||||
if (s.startsWith("#")) {
|
||||
@ -242,7 +244,7 @@ public final class ExcludeVMPlugin implements Plugin {
|
||||
|
||||
byte[] content = builder.toString().getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
return orig.create(content);
|
||||
return orig.copyWithContent(content);
|
||||
}
|
||||
|
||||
private static String jvmlib() {
|
||||
|
@ -37,10 +37,11 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import jdk.tools.jlink.internal.PathModuleEntry;
|
||||
import jdk.tools.jlink.internal.PathResourcePoolEntry;
|
||||
import jdk.tools.jlink.plugin.PluginException;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
import jdk.tools.jlink.plugin.Plugin;
|
||||
import jdk.tools.jlink.internal.Utils;
|
||||
|
||||
@ -64,12 +65,12 @@ public class FileCopierPlugin implements Plugin {
|
||||
/**
|
||||
* Symbolic link to another path.
|
||||
*/
|
||||
public static abstract class SymImageFile extends PathModuleEntry {
|
||||
public static abstract class SymImageFile extends PathResourcePoolEntry {
|
||||
|
||||
private final String targetPath;
|
||||
|
||||
public SymImageFile(String targetPath, String module, String path,
|
||||
ModuleEntry.Type type, Path file) {
|
||||
ResourcePoolEntry.Type type, Path file) {
|
||||
super(module, path, type, file);
|
||||
this.targetPath = targetPath;
|
||||
}
|
||||
@ -82,7 +83,7 @@ public class FileCopierPlugin implements Plugin {
|
||||
private static final class SymImageFileImpl extends SymImageFile {
|
||||
|
||||
public SymImageFileImpl(String targetPath, Path file, String module,
|
||||
String path, ModuleEntry.Type type) {
|
||||
String path, ResourcePoolEntry.Type type) {
|
||||
super(targetPath, module, path, type, file);
|
||||
}
|
||||
}
|
||||
@ -90,11 +91,11 @@ public class FileCopierPlugin implements Plugin {
|
||||
private static final class DirectoryCopy implements FileVisitor<Path> {
|
||||
|
||||
private final Path source;
|
||||
private final ModulePool pool;
|
||||
private final ResourcePoolBuilder pool;
|
||||
private final String targetDir;
|
||||
private final List<SymImageFile> symlinks = new ArrayList<>();
|
||||
|
||||
DirectoryCopy(Path source, ModulePool pool, String targetDir) {
|
||||
DirectoryCopy(Path source, ResourcePoolBuilder pool, String targetDir) {
|
||||
this.source = source;
|
||||
this.pool = pool;
|
||||
this.targetDir = targetDir;
|
||||
@ -128,7 +129,7 @@ public class FileCopierPlugin implements Plugin {
|
||||
}
|
||||
SymImageFileImpl impl = new SymImageFileImpl(symTarget.toString(),
|
||||
file, path, Objects.requireNonNull(file.getFileName()).toString(),
|
||||
ModuleEntry.Type.OTHER);
|
||||
ResourcePoolEntry.Type.OTHER);
|
||||
symlinks.add(impl);
|
||||
} else {
|
||||
addFile(pool, file, path);
|
||||
@ -152,14 +153,14 @@ public class FileCopierPlugin implements Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
private static void addFile(ModulePool pool, Path file, String path)
|
||||
private static void addFile(ResourcePoolBuilder pool, Path file, String path)
|
||||
throws IOException {
|
||||
Objects.requireNonNull(pool);
|
||||
Objects.requireNonNull(file);
|
||||
Objects.requireNonNull(path);
|
||||
ModuleEntry impl = ModuleEntry.create(
|
||||
ResourcePoolEntry impl = ResourcePoolEntry.create(
|
||||
"/" + FAKE_MODULE + "/other/" + path,
|
||||
ModuleEntry.Type.OTHER, file);
|
||||
ResourcePoolEntry.Type.OTHER, file);
|
||||
try {
|
||||
pool.add(impl);
|
||||
} catch (Exception ex) {
|
||||
@ -211,7 +212,7 @@ public class FileCopierPlugin implements Plugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ModulePool in, ModulePool out) {
|
||||
public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
|
||||
in.transformAndCopy((file) -> {
|
||||
return file;
|
||||
}, out);
|
||||
@ -238,6 +239,8 @@ public class FileCopierPlugin implements Plugin {
|
||||
} catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
|
||||
return out.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -31,9 +31,10 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
import jdk.tools.jlink.plugin.PluginException;
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
|
||||
import jdk.tools.jlink.plugin.Plugin;
|
||||
|
||||
/**
|
||||
@ -145,22 +146,22 @@ public final class GenerateJLIClassesPlugin implements Plugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ModulePool in, ModulePool out) {
|
||||
public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
|
||||
in.entries().forEach(data -> {
|
||||
if (("/java.base/" + BMH + ".class").equals(data.getPath())) {
|
||||
if (("/java.base/" + BMH + ".class").equals(data.path())) {
|
||||
// Add BoundMethodHandle unchanged
|
||||
out.add(data);
|
||||
speciesTypes.forEach(types -> generateConcreteClass(types, data, out));
|
||||
} else {
|
||||
if (!out.contains(data)) {
|
||||
out.add(data);
|
||||
}
|
||||
out.add(data);
|
||||
}
|
||||
});
|
||||
|
||||
return out.build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void generateConcreteClass(String types, ModuleEntry data, ModulePool out) {
|
||||
private void generateConcreteClass(String types, ResourcePoolEntry data, ResourcePoolBuilder out) {
|
||||
try {
|
||||
// Generate class
|
||||
Map.Entry<String, byte[]> result = (Map.Entry<String, byte[]>)
|
||||
@ -169,12 +170,10 @@ public final class GenerateJLIClassesPlugin implements Plugin {
|
||||
byte[] bytes = result.getValue();
|
||||
|
||||
// Add class to pool
|
||||
ModuleEntry ndata = ModuleEntry.create(
|
||||
ResourcePoolEntry ndata = ResourcePoolEntry.create(
|
||||
"/java.base/" + className + ".class",
|
||||
bytes);
|
||||
if (!out.contains(ndata)) {
|
||||
out.add(ndata);
|
||||
}
|
||||
out.add(ndata);
|
||||
} catch (Exception ex) {
|
||||
throw new PluginException(ex);
|
||||
}
|
||||
|
@ -42,10 +42,11 @@ import java.util.stream.Stream;
|
||||
import jdk.internal.org.objectweb.asm.ClassReader;
|
||||
import jdk.tools.jlink.internal.ResourcePrevisitor;
|
||||
import jdk.tools.jlink.internal.StringTable;
|
||||
import jdk.tools.jlink.plugin.LinkModule;
|
||||
import jdk.tools.jlink.plugin.ModuleEntry;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolModule;
|
||||
import jdk.tools.jlink.plugin.PluginException;
|
||||
import jdk.tools.jlink.plugin.ModulePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolEntry;
|
||||
import jdk.tools.jlink.plugin.Plugin;
|
||||
import sun.util.cldr.CLDRBaseLocaleDataMetaInfo;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
@ -151,24 +152,26 @@ public final class IncludeLocalesPlugin implements Plugin, ResourcePrevisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ModulePool in, ModulePool out) {
|
||||
public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
|
||||
in.transformAndCopy((resource) -> {
|
||||
if (resource.getModule().equals(MODULENAME)) {
|
||||
String path = resource.getPath();
|
||||
if (resource.moduleName().equals(MODULENAME)) {
|
||||
String path = resource.path();
|
||||
resource = predicate.test(path) ? resource: null;
|
||||
if (resource != null &&
|
||||
resource.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
|
||||
byte[] bytes = resource.getBytes();
|
||||
resource.type().equals(ResourcePoolEntry.Type.CLASS_OR_RESOURCE)) {
|
||||
byte[] bytes = resource.contentBytes();
|
||||
ClassReader cr = new ClassReader(bytes);
|
||||
if (Arrays.stream(cr.getInterfaces())
|
||||
.anyMatch(i -> i.contains(METAINFONAME)) &&
|
||||
stripUnsupportedLocales(bytes, cr)) {
|
||||
resource = resource.create(bytes);
|
||||
resource = resource.copyWithContent(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
return resource;
|
||||
}, out);
|
||||
|
||||
return out.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -205,14 +208,14 @@ public final class IncludeLocalesPlugin implements Plugin, ResourcePrevisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void previsit(ModulePool resources, StringTable strings) {
|
||||
public void previsit(ResourcePool resources, StringTable strings) {
|
||||
final Pattern p = Pattern.compile(".*((Data_)|(Names_))(?<tag>.*)\\.class");
|
||||
Optional<LinkModule> optMod = resources.findModule(MODULENAME);
|
||||
Optional<ResourcePoolModule> optMod = resources.moduleView().findModule(MODULENAME);
|
||||
|
||||
// jdk.localedata module validation
|
||||
if (optMod.isPresent()) {
|
||||
LinkModule module = optMod.get();
|
||||
Set<String> packages = module.getAllPackages();
|
||||
ResourcePoolModule module = optMod.get();
|
||||
Set<String> packages = module.packages();
|
||||
if (!packages.containsAll(LOCALEDATA_PACKAGES)) {
|
||||
throw new PluginException(PluginsResourceBundle.getMessage(NAME + ".missingpackages") +
|
||||
LOCALEDATA_PACKAGES.stream()
|
||||
@ -221,7 +224,7 @@ public final class IncludeLocalesPlugin implements Plugin, ResourcePrevisitor {
|
||||
}
|
||||
|
||||
available = Stream.concat(module.entries()
|
||||
.map(md -> p.matcher(md.getPath()))
|
||||
.map(md -> p.matcher(md.path()))
|
||||
.filter(m -> m.matches())
|
||||
.map(m -> m.group("tag").replaceAll("_", "-")),
|
||||
Stream.concat(Stream.of(jaJPJPTag), Stream.of(thTHTHTag)))
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user