This commit is contained in:
Alejandro Murillo 2016-07-28 16:43:37 +00:00
commit 8a05f12710
181 changed files with 6077 additions and 2694 deletions

View File

@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
tzdata2016d
tzdata2016f

View File

@ -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 -

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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...

View File

@ -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

View File

@ -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

View File

@ -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, \

View File

@ -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;

View File

@ -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;

View File

@ -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;
}});
}
}

View File

@ -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));
}
}

View File

@ -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;
}
});
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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());
}

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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
{

View File

@ -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;

View File

@ -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";

View File

@ -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.
*/

View File

@ -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 resources
* 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);

View File

@ -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;

View File

@ -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());
}
}
}
}
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);

View File

@ -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;");

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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");

View File

@ -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}

View File

@ -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;
}

View File

@ -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();

View File

@ -1388,9 +1388,7 @@ public abstract class Toolkit {
// ensure that the proper libraries are loaded
loadLibraries();
initAssistiveTechnologies();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
initIDs();
}
/**

View File

@ -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;
}
}
}

View File

@ -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
}

View File

@ -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));
}
/**

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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)
);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
/**

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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)) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -26,8 +26,7 @@
#include <signal.h>
#include <stdlib.h>
int getNativeScaleFactor();
int getScale(const char *uiScale);
double getNativeScaleFactor();
#endif

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;

View File

@ -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) {

View File

@ -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) {

View File

@ -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);

View File

@ -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> {

View File

@ -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);
}
/**

View File

@ -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);
}
/**

View File

@ -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;

View File

@ -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");
}

View File

@ -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();
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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");
}
};

View File

@ -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 {

View File

@ -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,

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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() {

View File

@ -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

View File

@ -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);
}

View File

@ -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