Compare commits

..

59 Commits
198 ... 236

Author SHA1 Message Date
Vitaly Provodin
b2cbcbeeef add exclude list for Scale2 test runs 2021-12-17 15:22:18 +07:00
Vitaly Provodin
aba2a258bb exclude java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java due to 8134231 2021-12-17 15:22:15 +07:00
Vladimir Dvorak
53c9198350 JBR-3167 update os.version for tests crashing GNOME on Ubuntu-21.04 2021-12-15 10:21:54 +07:00
Prasanta Sadhukhan
e27b2fbf84 8272232: javax/swing/JTable/4275046/bug4275046.java failed with "Expected value in the cell: 'rededited' but found 'redEDITED'."
8257540: javax/swing/JFileChooser/8041694/bug8041694.java failed with "RuntimeException: The selected directory name is not the expected 'd ' but 'D '."

Reviewed-by: serb
(cherry picked from commit cec6c068b0)
2021-12-13 10:37:53 +07:00
Vitaly Provodin
a5c9a208ed enable fixed hotspot tests to regular runs 2021-12-11 08:24:07 +07:00
Leonid Mesnik
86b93a57af 8225313: serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorStatObjectCorrectnessTest.java failed with Unexpected high difference percentage
Reviewed-by: dholmes, kevinw

(cherry picked from commit 09e5321763)
2021-12-11 08:21:52 +07:00
Vitaly Provodin
c838f55dd9 enable fixed tests to regular runs 2021-12-11 06:52:53 +07:00
Alexander Zuev
8d188ad27f 8017175: [TESTBUG] javax/swing/JPopupMenu/4634626/bug4634626.java sometimes failed on mac
Reviewed-by: serb
(cherry picked from commit 4c3491bfa5)
2021-12-11 06:47:13 +07:00
Alexander Zuev
d87fc06c41 8268284: javax/swing/JComponent/7154030/bug7154030.java fails with "Exception: Failed to hide opaque button"
Reviewed-by: serb
(cherry picked from commit 534f00510e)
2021-12-11 06:46:08 +07:00
Naoto Sato
b17c748949 7008363: TEST_BUG: test/java/lang/StringCoding/CheckEncodings.sh does nothing and is very slow at that
Reviewed-by: iris, lancea, bpb, whuang
(cherry picked from commit 8a3e0a1fc1)
2021-12-11 06:44:15 +07:00
Alexander Zvegintsev
03783189d0 8233648: [TESTBUG] DefaultMenuBarTest.java failing on macos
Reviewed-by: pbansal, serb, psadhukhan, prr
(cherry picked from commit 46b5bfbc38)
2021-12-11 06:43:21 +07:00
Alisen Chung
05fbf8507c 8233558: [TESTBUG] WindowOwnedByEmbeddedFrameTest.java fails on macos
Reviewed-by: serb, kizune, prr
(cherry picked from commit d1e3ca4ee3)
2021-12-11 06:41:56 +07:00
Jayathirth D V
80de7efe15 8213120: java/awt/TextArea/AutoScrollOnSelectAndAppend/AutoScrollOnSelectAndAppend.java fails on mac10.13
Reviewed-by: psadhukhan

(cherry picked from commit 2f979ecb5b)
2021-12-11 06:40:20 +07:00
Alexander Zuev
6d1add0393 8169468: NoResizeEventOnDMChangeTest.java fails because FS Window didn't receive all resizes!
Reviewed-by: serb

(cherry picked from commit b0a463fa59)
2021-12-11 06:39:03 +07:00
Jayathirth D V
f57241bcf8 8255898: Test java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java fails on Mac OS
Reviewed-by: prr, serb
(cherry picked from commit 947d52c4c3)
2021-12-11 06:36:28 +07:00
Alexander Zuev
3fca5bee90 8202667: java/awt/Debug/DumpOnKey/DumpOnKey.java times out on Windows
Reviewed-by: prr
(cherry picked from commit cd778f5b04)
2021-12-11 06:35:00 +07:00
Jayathirth D V
60330c9b3e 8255724: [XRender] the BlitRotateClippedArea test fails on Linux in the XR pipeline
Reviewed-by: psadhukhan
(cherry picked from commit dcd6e0da24)
2021-12-11 06:30:30 +07:00
Phil Race
4a16c3b8c8 8192931: Regression test java/awt/font/TextLayout/CombiningPerf.java fails
Reviewed-by: serb, jdv, kizune
(cherry picked from commit 54a29a4470)
2021-12-11 06:26:37 +07:00
Alexander Zvegintsev
2ece56c057 8196440: Regression automated Test 'java/awt/TrayIcon/PopupMenuLeakTest/PopupMenuLeakTest.java' fails
Reviewed-by: serb, psadhukhan
(cherry picked from commit f610ef0dbc)
2021-12-11 06:23:54 +07:00
Alexander Zuev
c3a506172b 8196017: java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java fails
Reviewed-by: serb
(cherry picked from commit b7104ba9a9)
2021-12-11 06:23:19 +07:00
Alexander Zvegintsev
c81d4030eb 6854300: [TEST_BUG] java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_3.java fails in jdk6u14 & jdk7
Reviewed-by: serb
(cherry picked from commit a1ec4f9618)
2021-12-11 06:21:28 +07:00
Alexander Zuev
32fb930e85 8168388: GetMousePositionTest fails with the message "Mouse position should not be null"
Reviewed-by: psadhukhan, serb
(cherry picked from commit 0c3eaea11c)
2021-12-11 06:18:53 +07:00
Pankaj Bansal
0ef1d9a4a9 8198626: java/awt/KeyboardFocusmanager/TypeAhead/TestDialogTypeAhead.html fails on mac
Reviewed-by: serb
(cherry picked from commit a60e91259b)
2021-12-11 06:18:21 +07:00
Vitaly Provodin
07ee0a2471 exclude javax/swing tests on mac-aarch64 due to 8277816 2021-12-11 05:48:20 +07:00
Aleksandr Veselov
c4cb87ff06 JBR-4107 A11y: macOS - wrong frame position if window is not on primary screen 2021-12-10 18:26:06 +03:00
Alexander Lobas
6b36a9227d JBR-3442 Native file dialog on OSX (for open file) doesn't allow pasting path
(cherry-picked from commit 7d8cc524ca)
2021-12-10 07:28:14 +07:00
Vitaly Provodin
83ca27f8b2 exclude javax/swing/border/TestTitledBorderLeak.java on windows due to 8213531 2021-12-10 05:23:35 +07:00
Maxim Kartashev
c539ca4ddf fixup! JBR-4061 Specify build user for the build
Specify build user via the environment variable rather than the
configure option because the latter isn't supported for OpenJDK17u.
2021-12-09 09:31:09 +03:00
Mandy Chung
51ec2c610e JBR-4062 8276650: GenGraphs does not produce deterministic output
Reviewed-by: iris
(cherry picked from commit e21b5c7b37)
2021-12-08 16:44:46 +03:00
Jaikiran Pai
2b8ee942e0 JBR-4062 8258117: jar tool sets the time stamp of module-info.class entries to the current time
Reviewed-by: lancea, ihse, alanb
(cherry picked from commit a81e4fc07b)
2021-12-08 16:31:20 +03:00
Andrew Leonard
9b17148ef4 JBR-4062 8276764: Enable deterministic file content ordering for Jar and Jmod
Reviewed-by: mchung, ihse
(cherry picked from commit 24e586a043)
2021-12-08 15:10:06 +03:00
Magnus Ihse Bursie
02289f478f JBR-4062 8277069: [REDO] JDK-8276743 Make openjdk build Zip Archive generation "reproducible"
Co-authored-by: Andrew Leonard <aleonard@openjdk.org>
Co-authored-by: Magnus Ihse Bursie <ihse@openjdk.org>
Reviewed-by: erikj
(cherry picked from commit c93552c8bb)
2021-12-08 14:55:59 +03:00
Vitaly Provodin
2f0eb2bba8 JBR-4067 fix misprint with applying obsolete exclude_jcef_module.patch 2021-12-08 15:17:32 +07:00
Vitaly Provodin
740bf2b3e5 JBR-3756 remove JNF from mac-aarch64 binaries 2021-12-08 15:17:32 +07:00
Denis Fokin
88d7361bd9 JBR-4038 [JBR17] Force Touch events are not supported on macOS
Added missing files and handlers from JBR11
2021-12-07 19:31:12 +01:00
Dmitry Batrak
87c6482c0e JBR-4084 Default font '. AppleSystemUIFont' does not have bold weight on Chinese characters
(cherry picked from commit 4fde082d53)
2021-12-06 19:22:24 +03:00
Maxim Kartashev
b2a9372d70 JBR-3899 SIGSEGV at [libjvm] _ZN23JfrNetworkInterfaceName11on_rotationEv
Prevent JfrNetworkInterfaceName::on_rotation() to dereference a
potentially NULL pointer.
2021-12-06 19:03:53 +03:00
Dmitry Batrak
d0d8a63e0b JBR-4072 Migrate font fallback implementation on macOS to cascade lists
(cherry picked from commit a155760e94)
2021-12-06 17:59:44 +03:00
Maxim Kartashev
09c200ccfd fixup! JBR-3833 ServerSocketChannel.open(StandardProtocolFamily.UNIX) fails with IAE with non-standard filesystems on JBR17
Windows implementation of PipeImpl (that is used in the
ServerSockerChannel implementation) probes for the availability of Unix
Domain Sockets by trying to bind to a unique temporary name.  That call
throws IAE when a non-default Java file system is installed while the
probing code (PipeImpl.createListener()) only expects
UnsupportedOperationException or IOException.

The fix is to re-throw UOE instead of IAE in
UnixDomainSockets.genrateTempName(). This is more consistent with the
definition of the excpetion purpose ("requested operation is not
supported"). So with this change, a loopback network socket will be used
to implement a pipe on a non-default Java file system. Also, pipes do
not rely on the default Java file system on other platforms (Linux,
MacOS) as well.
2021-12-06 11:44:54 +03:00
Vitaly Provodin
42a22e0cc4 JBR-4082 create JBR & JBRSDK installer packages 2021-12-06 05:16:12 +07:00
Artem Semenov
71d54051d2 JBR-4012 On Idea Vo often speeks selected element of tables, lists, and trees. 2021-12-03 13:57:07 +03:00
Alexey Ushakov
d4fc6bc380 JBR-4060 [JBR17+Metal] Flickering on button's shadow
Removed unnecessary global flag. Optimized mask cache texture clearing code.
2021-12-03 01:38:41 +01:00
Vitaly Provodin
1e1f71f907 exclude failing tests #198.2 cycle 2021-12-03 07:24:05 +07:00
Prasanta Sadhukhan
6d26c9353f 8273578: javax/swing/JMenu/4515762/bug4515762.java fails on macOS 12
Reviewed-by: jdv, serb

(cherry picked from commit 45adc9227a)
2021-12-03 07:24:05 +07:00
Alexander Zvegintsev
adabf8c677 8202932: java/awt/Component/NativeInLightShow/NativeInLightShow.java fails
Reviewed-by: serb
(cherry picked from commit 7cf68b1901)
2021-12-03 04:40:30 +07:00
Maxim Kartashev
5e0ec47ce9 JBR-4061 Specify build user for the build 2021-12-02 08:56:21 +03:00
Andrew Leonard
9ec9457d8b JBR-4062 8277762: Allow configuration of HOTSPOT_BUILD_USER
Reviewed-by: erikj
2021-12-02 08:29:16 +03:00
Maxim Kartashev
e1a1b6814d JBR-4063 macOS: update build scripts to produce more deterministic output
Make mkimages.sh produce more deterministic .tar.gz archives on MacOS.
NB: build notarization is not in the scope of this change.
2021-12-01 14:33:59 +03:00
Maxim Kartashev
944797005c JBR-4033 Linux: update build scripts to produce more deterministic output
This commits achieves almost the same build output with the same build
input on Linux. Exceptions are:
- class files timestamps differ in jrt-fs.jar (for all output),
- class files timestamps differ in all the jmod files (for
  jbrsdk...tar.gz).
NB: jbrsdk...test...tar.gz does not need to be deterministic.

This was achieved mainly by
- setting several environment variables (SOURCE_DATE_EPOCH, TZ),
- providing the necessary options to the configure script,
- setting the timestamp of all files that make up the resulting
  archive to SORUCE_DATE_EPOCH and normalizing the list of said
  files before archiving.
2021-12-01 14:33:59 +03:00
Ioi Lam
507f4d716a JBR-4032 8273092: Sort classlist in JDK image
NB: this commit has been adopted for version 17.

Reviewed-by: redestad, ihse, dfuchs
(based on commit 1996f649a3)
2021-12-01 14:33:59 +03:00
Ioi Lam
67c24c9b88 JBR-4032 8272113: Build compare script fails with differences in classlist
Reviewed-by: tschatzl, hseigel
(cherry picked from commit 272fcb423a)
2021-12-01 14:33:59 +03:00
Andrew Leonard
2ef4de692d JBR-4032 8276654: element-list order is non deterministic
Reviewed-by: ihse
(cherry picked from commit 14d66bd438)
2021-12-01 14:33:59 +03:00
Jaikiran Pai
f20b2dca0f JBR-4032 8231640: (prop) Canonical property storage
Reviewed-by: rriggs, smarks, dfuchs, ihse
(cherry picked from commit af50772d39)
2021-12-01 14:33:59 +03:00
Maxim Kartashev
0b9397cf4c JBR-4032 Correct reproducible builds documentation 2021-12-01 14:33:59 +03:00
Magnus Ihse Bursie
392cf1c31a JBR-4032 8275745: Reproducible copyright headers
Reviewed-by: ihse, erikj
(cherry picked from commit a0227965bb)
2021-12-01 14:33:59 +03:00
Magnus Ihse Bursie
b269750318 JBR-4032 8276746: Add section on reproducible builds in building.md
Reviewed-by: erikj, sgehwolf, aleonard
(cherry picked from commit 59c3dcc761)
2021-12-01 14:33:58 +03:00
Jaikiran Pai
0676b50884 JBR-4032 8275509: ModuleDescriptor.hashCode isn't reproducible across builds
Reviewed-by: alanb, ihse
(cherry picked from commit 396132ff1e)
2021-12-01 14:33:58 +03:00
Maxim Kartashev
4df6fbd251 JBR-4059 Create Dockerfile for building on AArch64 Linux 2021-12-01 08:27:52 +03:00
bobpengxie
006cd74964 8274293: Build failure on macOS with Xcode 13.0 as vfork is deprecated
Reviewed-by: alanb, stuefe, rriggs
(cherry picked from commit 252aaa9249)
2021-11-30 09:19:46 +01:00
113 changed files with 3222 additions and 1692 deletions

View File

@@ -96,6 +96,7 @@
<li><a href="#specific-build-issues">Specific Build Issues</a></li>
<li><a href="#getting-help">Getting Help</a></li>
</ul></li>
<li><a href="#reproducible-builds">Reproducible Builds</a></li>
<li><a href="#hints-and-suggestions-for-advanced-users">Hints and Suggestions for Advanced Users</a><ul>
<li><a href="#bash-completion">Bash Completion</a></li>
<li><a href="#using-multiple-configurations">Using Multiple Configurations</a></li>
@@ -884,6 +885,32 @@ spawn failed</code></pre>
<h3 id="getting-help">Getting Help</h3>
<p>If none of the suggestions in this document helps you, or if you find what you believe is a bug in the build system, please contact the Build Group by sending a mail to <a href="mailto:build-dev@openjdk.java.net">build-dev@openjdk.java.net</a>. Please include the relevant parts of the configure and/or build log.</p>
<p>If you need general help or advice about developing for the JDK, you can also contact the Adoption Group. See the section on <a href="#contributing-to-openjdk">Contributing to OpenJDK</a> for more information.</p>
<h2 id="reproducible-builds">Reproducible Builds</h2>
<p>Build reproducibility is the property of getting exactly the same bits out when building, every time, independent on who builds the product, or where. This is for many reasons a harder goal than it initially appears, but it is an important goal, for security reasons and others. Please see <a href="https://reproducible-builds.org">Reproducible Builds</a> for more information about the background and reasons for reproducible builds.</p>
<p>Currently, it is not possible to build OpenJDK fully reproducibly, but getting there is an ongoing effort. There are some things you can do to minimize non-determinism and make a larger part of the build reproducible:</p>
<ul>
<li>Turn on build system support for reproducible builds</li>
</ul>
<p>Add the flag <code>--enable-reproducible-build</code> to your <code>configure</code> command line. This will turn on support for reproducible builds where it could otherwise be lacking.</p>
<ul>
<li>Do not rely on <code>configure</code>'s default adhoc version strings</li>
</ul>
<p>Default adhoc version strings OPT segment include user name, source directory and timestamp. You can either override just the OPT segment using <code>--with-version-opt=&lt;any fixed string&gt;</code>, or you can specify the entire version string using <code>--with-version-string=&lt;your version&gt;</code>.</p>
<ul>
<li>Specify how the build sets <code>SOURCE_DATE_EPOCH</code></li>
</ul>
<p>The JDK build system will set the <code>SOURCE_DATE_EPOCH</code> environment variable during building, depending on the value of the <code>--with-source-date</code> option for <code>configure</code>. The default value is <code>updated</code>, which means that <code>SOURCE_DATE_EPOCH</code> will be set to the current time each time you are running <code>make</code>.</p>
<p>The <a href="https://reproducible-builds.org/docs/source-date-epoch/"><code>SOURCE_DATE_EPOCH</code> environment variable</a> is an industry standard, that many tools, such as gcc, recognize, and use in place of the current time when generating output.</p>
<p>For reproducible builds, you need to set this to a fixed value. You can use the special value <code>version</code> which will use the nominal release date for the current JDK version, or a value describing a date, either an epoch based timestamp as an integer, or a valid ISO-8601 date.</p>
<p><strong>Hint:</strong> If your build environment already sets <code>SOURCE_DATE_EPOCH</code>, you can propagate this using <code>--with-source-date=$SOURCE_DATE_EPOCH</code>.</p>
<ul>
<li>Specify a hotspot build time</li>
</ul>
<p>Set a fixed hotspot build time. This will be included in the hotspot library (<code>libjvm.so</code> or <code>jvm.dll</code>) and defaults to the current time when building hotspot. Use <code>--with-hotspot-build-time=&lt;any fixed string&gt;</code> for reproducible builds. It's a string so you don't need to format it specifically, so e.g. <code>n/a</code> will do. Another solution is to use the <code>SOURCE_DATE_EPOCH</code> variable, e.g. <code>--with-hotspot-build-time=$(date --date=@$SOURCE_DATE_EPOCH)</code>.</p>
<ul>
<li>Copyright year</li>
</ul>
<p>The copyright year in some generated text files are normally set to the current year. This can be overridden by <code>--with-copyright-year=&lt;year&gt;</code>. For fully reproducible builds, this needs to be set to a fixed value.</p>
<h2 id="hints-and-suggestions-for-advanced-users">Hints and Suggestions for Advanced Users</h2>
<h3 id="bash-completion">Bash Completion</h3>
<p>The <code>configure</code> and <code>make</code> commands tries to play nice with bash command-line completion (using <code>&lt;tab&gt;</code> or <code>&lt;tab&gt;&lt;tab&gt;</code>). To use this functionality, make sure you enable completion in your <code>~/.bashrc</code> (see instructions for bash in your operating system).</p>

View File

@@ -1503,6 +1503,68 @@ If you need general help or advice about developing for the JDK, you can also
contact the Adoption Group. See the section on [Contributing to OpenJDK](
#contributing-to-openjdk) for more information.
## Reproducible Builds
Build reproducibility is the property of getting exactly the same bits out when
building, every time, independent on who builds the product, or where. This is
for many reasons a harder goal than it initially appears, but it is an important
goal, for security reasons and others. Please see [Reproducible Builds](
https://reproducible-builds.org) for more information about the background and
reasons for reproducible builds.
Currently, it is not possible to build OpenJDK fully reproducibly, but getting
there is an ongoing effort. There are some things you can do to minimize
non-determinism and make a larger part of the build reproducible:
* Turn on build system support for reproducible builds
Add the flag `--enable-reproducible-build` to your `configure` command line.
This will turn on support for reproducible builds where it could otherwise be
lacking.
* Do not rely on `configure`'s default adhoc version strings
Default adhoc version strings OPT segment include user name, source directory
and timestamp. You can either override just the OPT segment using
`--with-version-opt=<any fixed string>`, or you can specify the entire version
string using `--with-version-string=<your version>`.
* Specify how the build sets `SOURCE_DATE_EPOCH`
The JDK build system will set the `SOURCE_DATE_EPOCH` environment variable
during building, depending on the value of the `--with-source-date` option for
`configure`. The default value is `updated`, which means that
`SOURCE_DATE_EPOCH` will be set to the current time each time you are running
`make`.
The [`SOURCE_DATE_EPOCH` environment variable](
https://reproducible-builds.org/docs/source-date-epoch/) is an industry
standard, that many tools, such as gcc, recognize, and use in place of the
current time when generating output.
For reproducible builds, you need to set this to a fixed value. You can use the
special value `version` which will use the nominal release date for the current
JDK version, or a value describing a date, either an epoch based timestamp as an
integer, or a valid ISO-8601 date.
**Hint:** If your build environment already sets `SOURCE_DATE_EPOCH`, you can
propagate this using `--with-source-date=$SOURCE_DATE_EPOCH`.
* Specify a hotspot build time
Set a fixed hotspot build time. This will be included in the hotspot library
(`libjvm.so` or `jvm.dll`) and defaults to the current time when building
hotspot. Use `--with-hotspot-build-time=<any fixed string>` for reproducible
builds. It's a string so you don't need to format it specifically, so e.g. `n/a`
will do. Another solution is to use the `SOURCE_DATE_EPOCH` variable, e.g.
`--with-hotspot-build-time=$(date --date=@$SOURCE_DATE_EPOCH)`.
* Copyright year
The copyright year in some generated text files are normally set to the current
year. This can be overridden by `--with-copyright-year=<year>`. For fully
reproducible builds, this needs to be set to a fixed value.
## Hints and Suggestions for Advanced Users
### Bash Completion

View File

@@ -0,0 +1,47 @@
# NOTE: This Dockerfile is meant to be used from the mkdocker_aarch64.sh script.
# Pull a concrete version of Linux that does NOT recieve updates after it's
# been created. This is so that the image is as stable as possible to make
# image creation reproducible.
# NB: this also means there may be no security-related fixes there, need to
# move the version to the next manually.
FROM arm64v8/ubuntu:focal-20211006
# Install the necessary build tools
RUN export DEBIAN_FRONTEND=noninteractive \
export DEBCONF_NONINTERACTIVE_SEEN=true && \
echo 'tzdata tzdata/Areas select Etc' | debconf-set-selections; \
echo 'tzdata tzdata/Zones/Etc select UTC' | debconf-set-selections; \
apt-get update -qy && \
apt-get install -qy \
autoconf \
build-essential \
bzip2 \
file \
g++-10=10.3.0-1ubuntu1~20.04 \
gcc-10=10.3.0-1ubuntu1~20.04 \
git \
libasound2-dev \
libcups2-dev \
libfontconfig1-dev \
libx11-dev \
libxext-dev \
libxrandr-dev \
libxrender-dev \
libxt-dev \
libxtst-dev \
make \
tar \
unzip \
zip && \
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 && \
apt-get clean -qy && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Set up boot JDK for building
COPY boot_jdk.tar.gz /jdk17/
RUN cd /jdk17 && tar --strip-components=1 -xzf boot_jdk.tar.gz && rm /jdk17/boot_jdk.tar.gz
ENV BOOT_JDK=/jdk17
RUN git config --global user.email "teamcity@jetbrains.com" && \
git config --global user.name "builduser"

View File

@@ -0,0 +1,26 @@
#!/bin/bash -x
# This script creates a Docker image suitable for building AArch64 variant
# of the JetBrains Runtime version 17.
BOOT_JDK_REMOTE_FILE=zulu17.30.15-ca-jdk17.0.1-linux_aarch64.tar.gz
BOOT_JDK_SHA=4d9c9116eb0cdd2d7fb220d6d27059f4bf1b7e95cc93d5512bd8ce3791af86c7
BOOT_JDK_LOCAL_FILE=boot_jdk.tar.gz
if [ ! -f $BOOT_JDK_LOCAL_FILE ]; then
# Obtain "boot JDK" from outside of the container.
wget -nc https://cdn.azul.com/zulu/bin/${BOOT_JDK_REMOTE_FILE} -O $BOOT_JDK_LOCAL_FILE
else
echo "boot JDK \"$BOOT_JDK_LOCAL_FILE\" present, skipping download"
fi
# Verify that what we've downloaded can be trusted.
sha256sum -c - <<EOF
$BOOT_JDK_SHA *$BOOT_JDK_LOCAL_FILE
EOF
docker build -t jbr17buildenv -f Dockerfile.aarch64 .
# NB: the resulting container can (and should) be used without the network
# connection (--network none) during build in order to reduce the chance
# of build contamination.

View File

@@ -6,6 +6,38 @@ do_reset_changes=0
do_reset_dcevm=0
HEAD_REVISION=0
OS_NAME=$(uname -s)
# Enable reproducible builds
TZ=UTC
export TZ
SOURCE_DATE_EPOCH="$(git log -1 --pretty=%ct)"
export SOURCE_DATE_EPOCH
USER=builduser
export USER
case "$OS_NAME" in
Linux)
COPYRIGHT_YEAR="$(date --utc --date=@$SOURCE_DATE_EPOCH +%Y)"
BUILD_TIME="$(date --utc --date=@$SOURCE_DATE_EPOCH +%F)"
REPRODUCIBLE_TAR_OPTS="--mtime=@$SOURCE_DATE_EPOCH --owner=0 --group=0 --numeric-owner --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime"
;;
Darwin)
COPYRIGHT_YEAR="$(date -u -r $SOURCE_DATE_EPOCH +%Y)"
BUILD_TIME="$(date -u -r $SOURCE_DATE_EPOCH +%F)"
TOUCH_TIME="$(date -u -r $SOURCE_DATE_EPOCH +%Y%m%d%H%M.%S)"
REPRODUCIBLE_TAR_OPTS="--uid 0 --gid 0 --numeric-owner"
;;
*)
# TODO: Windows
;;
esac
REPRODUCIBLE_BUILD_OPTS="--enable-reproducible-build
--with-source-date=$SOURCE_DATE_EPOCH
--with-hotspot-build-time=$BUILD_TIME
--with-copyright-year=$COPYRIGHT_YEAR
--with-native-debug-symbols=none"
function do_exit() {
exit_code=$1
[ $do_reset_changes -eq 1 ] && git checkout HEAD modules.list src/java.desktop/share/classes/module-info.java

View File

@@ -24,8 +24,6 @@ source jb/project/tools/common/scripts/common.sh
JBRSDK_BASE_NAME=jbrsdk-${JBSDK_VERSION}
[ -z "$bundle_type" ] && (git apply -p0 < jb/project/tools/patches/exclude_jcef_module.patch || exit $?)
sh configure \
--with-debug-level=release \
--with-vendor-name="${VENDOR_NAME}" \
@@ -35,7 +33,9 @@ sh configure \
--with-version-build="${JDK_BUILD_NUMBER}" \
--with-version-opt=b${build_number} \
--with-boot-jdk=${BOOT_JDK} \
--enable-cds=yes || exit $?
--enable-cds=yes \
$REPRODUCIBLE_BUILD_OPTS \
|| exit $?
make clean CONF=linux-aarch64-server-release || exit $?
make images CONF=linux-aarch64-server-release test-image || exit $?
@@ -54,9 +54,11 @@ echo Creating $JBSDK.tar.gz ...
sed 's/JBR/JBRSDK/g' ${BASE_DIR}/${JBRSDK_BUNDLE}/release > release
mv release ${BASE_DIR}/${JBRSDK_BUNDLE}/release
tar -pcf $JBSDK.tar \
# NB: --sort=name requires tar1.28
tar $REPRODUCIBLE_TAR_OPTS --sort=name -pcf $JBSDK.tar \
--exclude=*.debuginfo --exclude=demo --exclude=sample --exclude=man \
-C $BASE_DIR ${JBRSDK_BUNDLE} || exit $?
touch -c -d @$SOURCE_DATE_EPOCH $JBRSDK.tar
gzip $JBSDK.tar || exit $?
JBR_BUNDLE=jbr
@@ -75,10 +77,11 @@ echo Modifying release info ...
grep -v \"^JAVA_VERSION\" ${JSDK}/release | grep -v \"^MODULES\" >> ${BASE_DIR}/${JBR_BUNDLE}/release
echo Creating $JBR.tar.gz ...
tar -pcf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $?
tar $REPRODUCIBLE_TAR_OPTS --sort=name -pcf $JBR.tar -C $BASE_DIR ${JBR_BUNDLE} || exit $?
touch -c -d @$SOURCE_DATE_EPOCH $JBR.tar
gzip $JBR.tar || exit $?
JBRSDK_TEST=$JBRSDK_BASE_NAME-linux-test-aarch64-b$build_number
echo Creating $JBRSDK_TEST.tar.gz ...
tar -pcf $JBRSDK_TEST.tar -C $BASE_DIR --exclude='test/jdk/demos' test || exit $?
gzip $JBRSDK_TEST.tar || exit $?
gzip $JBRSDK_TEST.tar || exit $?

View File

@@ -50,7 +50,9 @@ function do_configure {
--with-version-build="$JDK_BUILD_NUMBER" \
--with-version-opt=b"$build_number" \
--with-boot-jdk="$BOOT_JDK" \
--enable-cds=yes || do_exit $?
--enable-cds=yes \
$REPRODUCIBLE_BUILD_OPTS \
|| do_exit $?
}
function create_image_bundle {
@@ -79,8 +81,14 @@ function create_image_bundle {
[ -f "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__arch_name"/lib/jcef_helper
echo Creating "$JBR".tar.gz ...
tar -pcf "$JBR".tar -C "$IMAGES_DIR" "$__arch_name" || do_exit $?
(cd "$IMAGES_DIR" &&
find "$__arch_name" -print0 | LC_ALL=C sort -z | \
tar $REPRODUCIBLE_TAR_OPTS \
--no-recursion --null -T - -cf "$JBR".tar) || do_exit $?
mv "$IMAGES_DIR"/"$JBR".tar ./"$JBR".tar
[ -f "$JBR".tar.gz ] && rm "$JBR.tar.gz"
touch -c -d "@$SOURCE_DATE_EPOCH" "$JBR".tar
gzip "$JBR".tar || do_exit $?
rm -rf "${IMAGES_DIR:?}"/"$__arch_name"
}
@@ -150,4 +158,4 @@ if [ -z "$bundle_type" ]; then
gzip "$JBRSDK_TEST".tar || do_exit $?
fi
do_exit 0
do_exit 0

View File

@@ -47,18 +47,14 @@ BOOT_JDK=${BOOT_JDK:=$(/usr/libexec/java_home -v 16)}
source jb/project/tools/common/scripts/common.sh
function copyJNF {
__contents_dir=$1
mkdir -p ${__contents_dir}/Frameworks
cp -Rp Frameworks/JavaNativeFoundation.framework ${__contents_dir}/Frameworks
}
function do_configure {
if [[ "${architecture}" == *aarch64* ]]; then
sh configure \
$WITH_DEBUG_LEVEL \
--with-vendor-name="${VENDOR_NAME}" \
--with-vendor-version-string="${VENDOR_VERSION_STRING}" \
--with-macosx-bundle-name-base=${VENDOR_VERSION_STRING} \
--with-macosx-bundle-id-base="com.jetbrains.jbr" \
--with-jvm-features=shenandoahgc \
--with-version-pre= \
--with-version-build="${JDK_BUILD_NUMBER}" \
@@ -69,19 +65,25 @@ function do_configure {
--enable-cds=no \
--with-extra-cflags="-F$(pwd)/Frameworks" \
--with-extra-cxxflags="-F$(pwd)/Frameworks" \
--with-extra-ldflags="-F$(pwd)/Frameworks" || do_exit $?
--with-extra-ldflags="-F$(pwd)/Frameworks" \
$REPRODUCIBLE_BUILD_OPTS \
|| do_exit $?
else
sh configure \
$WITH_DEBUG_LEVEL \
--with-vendor-name="$VENDOR_NAME" \
--with-vendor-version-string="$VENDOR_VERSION_STRING" \
--with-macosx-bundle-name-base=${VENDOR_VERSION_STRING} \
--with-macosx-bundle-id-base="com.jetbrains.jbr" \
--with-jvm-features=shenandoahgc \
--with-version-pre= \
--with-version-build="$JDK_BUILD_NUMBER" \
--with-version-opt=b"$build_number" \
--with-boot-jdk="$BOOT_JDK" \
--with-macosx-version-max="${MACOSX_VERSION_MAX:="10.12.00"}" \
--enable-cds=yes || do_exit $?
--enable-cds=yes \
$REPRODUCIBLE_BUILD_OPTS \
|| do_exit $?
fi
}
@@ -115,16 +117,17 @@ function create_image_bundle {
cp -R "$JSDK"/../MacOS "$JRE_CONTENTS"
cp "$JSDK"/../Info.plist "$JRE_CONTENTS"
if [[ "${architecture}" == *aarch64* ]]; then
# we can't notarize this library as usual framework (with headers and tbd-file)
# but single library notarizes correctly
copyJNF $JRE_CONTENTS
fi
[ -n "$bundle_type" ] && (cp -a $JCEF_PATH/Frameworks "$JRE_CONTENTS" || do_exit $?)
echo Creating "$JBR".tar.gz ...
COPYFILE_DISABLE=1 tar -pczf "$JBR".tar.gz --exclude='*.dSYM' --exclude='man' -C "$tmp" "$__arch_name" || do_exit $?
# Normalize timestamp
find "$tmp"/"$__arch_name" -print0 | xargs -0 touch -c -h -t "$TOUCH_TIME"
(cd "$tmp" &&
find "$__arch_name" -print0 | LC_ALL=C sort -z | \
COPYFILE_DISABLE=1 tar $REPRODUCIBLE_TAR_OPTS --no-recursion --null -T - \
-czf "$JBR".tar.gz --exclude='*.dSYM' --exclude='man') || do_exit $?
mv "$tmp"/"$JBR".tar.gz "$JBR".tar.gz
rm -rf "$tmp"
}
@@ -198,4 +201,4 @@ if [ -z "$bundle_type" ]; then
COPYFILE_DISABLE=1 tar -pczf "$JBRSDK_TEST".tar.gz -C $IMAGES_DIR --exclude='test/jdk/demos' test || do_exit $?
fi
do_exit 0
do_exit 0

View File

@@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/bash -x
APP_DIRECTORY=$1
APPL_USER=$2
@@ -54,17 +54,15 @@ function altool-upload() {
#immediately exit script with an error if a command fails
set -euo pipefail
file="$APP_NAME.zip"
#file="$APP_NAME.zip"
log "Zipping $file..."
rm -rf "$file"
ditto -c -k --sequesterRsrc --keepParent "$APP_DIRECTORY" "$file"
#log "Zipping $file..."
#rm -rf "$file"
#ditto -c -k --sequesterRsrc --keepParent "$APP_DIRECTORY" "$file"
log "Notarizing $file..."
log "Notarizing $APP_NAME..."
rm -rf "altool.init.out" "altool.check.out"
altool-upload "$file"
rm -rf "$file"
altool-upload "$APP_NAME"
notarization_info="$(grep -e "RequestUUID" "altool.init.out" | grep -oE '([0-9a-f-]{36})')"

View File

@@ -1,14 +1,17 @@
#!/bin/bash
#!/bin/bash -x
APP_DIRECTORY=$1
JB_CERT=$2
APPLICATION_PATH=$1
APP_NAME=$2
BUNDLE_ID=$3
JB_DEVELOPER_CERT=$4
JB_INSTALLER_CERT=$5
if [[ -z "$APP_DIRECTORY" ]] || [[ -z "$JB_CERT" ]]; then
if [[ -z "$APPLICATION_PATH" ]] || [[ -z "$JB_DEVELOPER_CERT" ]]; then
echo "Usage: $0 AppDirectory CertificateID"
exit 1
fi
if [[ ! -d "$APP_DIRECTORY" ]]; then
echo "AppDirectory '$APP_DIRECTORY' does not exist or not a directory"
if [[ ! -d "$APPLICATION_PATH" ]]; then
echo "AppDirectory '$APPLICATION_PATH' does not exist or not a directory"
exit 1
fi
@@ -20,43 +23,30 @@ function log() {
set -euo pipefail
# Cleanup files left from previous sign attempt (if any)
find "$APP_DIRECTORY" -name '*.cstemp' -exec rm '{}' \;
find "$APPLICATION_PATH" -name '*.cstemp' -exec rm '{}' \;
log "Signing libraries and executables..."
# -perm +111 searches for executables
for f in \
"Contents/Home/bin" \
"Contents/Home/lib"; do
if [ -d "$APP_DIRECTORY/$f" ]; then
find "$APP_DIRECTORY/$f" \
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \
-exec codesign --timestamp --force \
-v -s "$JB_CERT" --options=runtime \
"Contents/Home/lib" "Contents/MacOS" \
"Contents/Home/Frameworks" \
"Contents/Frameworks"; do
if [ -d "$APPLICATION_PATH/$f" ]; then
find "$APPLICATION_PATH/$f" \
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "*.tbd" -o -name "*.node" -o -perm +111 \) \
-exec codesign --timestamp \
-v -s "$JB_DEVELOPER_CERT" --options=runtime --force \
--entitlements entitlements.xml {} \;
fi
done
if [ -d "$APP_DIRECTORY/Contents/Frameworks" ]; then
log "Signing frameworks..."
for f in $APP_DIRECTORY/Contents/Frameworks/*; do
find "$f" \
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" \) \
-exec codesign --timestamp --force \
-v -s "$JB_CERT" \
--entitlements entitlements.xml {} \;
codesign --timestamp --force \
-v -s "$JB_CERT" --options=runtime \
--entitlements entitlements.xml "$f"
done
fi
log "Signing libraries in jars in $PWD"
# todo: add set -euo pipefail; into the inner sh -c
# `-e` prevents `grep -q && printf` loginc
# with `-o pipefail` there's no input for 'while' loop
find "$APP_DIRECTORY" -name '*.jar' \
-exec sh -c "set -u; unzip -l \"\$0\" | grep -q -e '\.dylib\$' -e '\.jnilib\$' -e '\.so\$' -e '^jattach\$' && printf \"\$0\0\" " {} \; |
find "$APPLICATION_PATH" -name '*.jar' \
-exec sh -c "set -u; unzip -l \"\$0\" | grep -q -e '\.dylib\$' -e '\.jnilib\$' -e '\.so\$' -e '\.tbd\$' -e '^jattach\$' && printf \"\$0\0\" " {} \; |
while IFS= read -r -d $'\0' file; do
log "Processing libraries in $file"
@@ -67,12 +57,13 @@ find "$APP_DIRECTORY" -name '*.jar' \
cp "$file" jarfolder && (cd jarfolder && jar xf "$filename" && rm "$filename")
find jarfolder \
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "jattach" \) \
-exec codesign --timestamp --force \
-v -s "$JB_CERT" --options=runtime \
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "*.tbd" -o -name "jattach" \) \
-exec codesign --timestamp \
--force \
-v -s "$JB_DEVELOPER_CERT" --options=runtime \
--entitlements entitlements.xml {} \;
(cd jarfolder; zip -q -r -o ../jar.jar .)
(cd jarfolder; zip -q -r -o -0 ../jar.jar .)
mv jar.jar "$file"
done
@@ -80,28 +71,41 @@ rm -rf jarfolder jar.jar
log "Signing other files..."
for f in \
"Contents/MacOS"; do
if [ -d "$APP_DIRECTORY/$f" ]; then
find "$APP_DIRECTORY/$f" \
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -perm +111 \) \
-exec codesign --timestamp --force \
-v -s "$JB_CERT" --options=runtime \
"Contents/Home/bin"; do
if [ -d "$APPLICATION_PATH/$f" ]; then
find "$APPLICATION_PATH/$f" \
-type f \( -name "*.jnilib" -o -name "*.dylib" -o -name "*.so" -o -name "*.tbd" -o -perm +111 \) \
-exec codesign --timestamp \
-v -s "$JB_DEVELOPER_CERT" --options=runtime --force \
--entitlements entitlements.xml {} \;
fi
done
#log "Signing executable..."
#codesign --timestamp \
# -v -s "$JB_CERT" --options=runtime \
# -v -s "$JB_DEVELOPER_CERT" --options=runtime \
# --force \
# --entitlements entitlements.xml "$APP_DIRECTORY/Contents/MacOS/idea"
# --entitlements entitlements.xml "$APPLICATION_PATH/Contents/MacOS/idea"
log "Signing whole app..."
codesign --timestamp \
-v -s "$JB_CERT" --options=runtime \
-v -s "$JB_DEVELOPER_CERT" --options=runtime \
--force \
--entitlements entitlements.xml "$APP_DIRECTORY"
--entitlements entitlements.xml "$APPLICATION_PATH"
BUILD_NAME=$(echo $APPLICATION_PATH | awk -F"/" '{ print $2 }')
log "Creating $APP_NAME.pkg..."
rm -rf "$APP_NAME.pkg"
pkgbuild --identifier $BUNDLE_ID --sign "$JB_INSTALLER_CERT" --root $APPLICATION_PATH \
--install-location /Library/Java/JavaVirtualMachines/${BUILD_NAME} ${APP_NAME}.pkg
#log "Signing whole app..."
#codesign --timestamp \
# -v -s "$JB_DEVELOPER_CERT" --options=runtime \
# --force \
# --entitlements entitlements.xml $APP_NAME.pkg
log "Verifying java is not broken"
find "$APP_DIRECTORY" \
find "$APPLICATION_PATH" \
-type f -name 'java' -perm +111 -exec {} -version \;

View File

@@ -12,8 +12,9 @@ BACKUP_JMODS=$2.backup
USERNAME=$3
PASSWORD=$4
CODESIGN_STRING=$5
NOTARIZE=$6
BUNDLE_ID=$7
JB_INSTALLER_CERT=$6
NOTARIZE=$7
BUNDLE_ID=$8
cd "$(dirname "$0")"
@@ -33,7 +34,7 @@ mkdir "$BACKUP_JMODS"
log "Unzipping $INPUT_FILE to $EXPLODED ..."
tar -xzvf "$INPUT_FILE" --directory $EXPLODED
BUILD_NAME="$(ls "$EXPLODED")"
sed -i '' s/BNDL/APPL/ $EXPLODED/$BUILD_NAME/Contents/Info.plist
#sed -i '' s/BNDL/APPL/ $EXPLODED/$BUILD_NAME/Contents/Info.plist
rm -f $EXPLODED/$BUILD_NAME/Contents/CodeResources
rm "$INPUT_FILE"
if test -d $EXPLODED/$BUILD_NAME/Contents/Home/jmods; then
@@ -42,7 +43,9 @@ fi
log "$INPUT_FILE extracted and removed"
APPLICATION_PATH="$EXPLODED/$BUILD_NAME"
APP_NAME=$(echo ${INPUT_FILE} | awk -F".tar" '{ print $1 }')
APPLICATION_PATH=$(sed "s/osx-//" <<< "$EXPLODED/$APP_NAME")
mv $EXPLODED/$BUILD_NAME $APPLICATION_PATH
find "$APPLICATION_PATH/Contents/Home/bin" \
-maxdepth 1 -type f -name '*.jnilib' -print0 |
@@ -79,7 +82,7 @@ limit=3
set +e
while [[ $attempt -le $limit ]]; do
log "Signing (attempt $attempt) $APPLICATION_PATH ..."
./sign.sh "$APPLICATION_PATH" "$CODESIGN_STRING"
./sign.sh "$APPLICATION_PATH" "$APP_NAME" "$BUNDLE_ID" "$CODESIGN_STRING" "$JB_INSTALLER_CERT"
ec=$?
if [[ $ec -ne 0 ]]; then
((attempt += 1))
@@ -92,6 +95,7 @@ while [[ $attempt -le $limit ]]; do
log "Signing done"
codesign -v "$APPLICATION_PATH" -vvvvv
log "Check sign done"
spctl -a -v $APPLICATION_PATH
((attempt += limit))
fi
done
@@ -102,13 +106,12 @@ if [ "$NOTARIZE" = "yes" ]; then
log "Notarizing..."
# shellcheck disable=SC1090
source "$HOME/.notarize_token"
APP_NAME=$(echo ${INPUT_FILE} | awk -F"." '{ print $1 }')
# Since notarization tool uses same file for upload token we have to trick it into using different folders, hence fake root
# Also it leaves copy of zip file in TMPDIR, so notarize.sh overrides it and uses FAKE_ROOT as location for temp TMPDIR
FAKE_ROOT="$(pwd)/fake-root"
mkdir -p "$FAKE_ROOT"
echo "Notarization will use fake root: $FAKE_ROOT"
./notarize.sh "$APPLICATION_PATH" "$APPLE_USERNAME" "$APPLE_PASSWORD" "$APP_NAME" "$BUNDLE_ID" "$FAKE_ROOT"
./notarize.sh "$APPLICATION_PATH" "$APPLE_USERNAME" "$APPLE_PASSWORD" "$APP_NAME.pkg" "$BUNDLE_ID" "$FAKE_ROOT"
rm -rf "$FAKE_ROOT"
set +e
@@ -124,10 +127,11 @@ log "Zipping $BUILD_NAME to $INPUT_FILE ..."
#cd "$EXPLODED"
#ditto -c -k --sequesterRsrc --keepParent "$BUILD_NAME" "../$INPUT_FILE"
if test -d $BACKUP_JMODS/jmods; then
mv $BACKUP_JMODS/jmods $EXPLODED/$BUILD_NAME/Contents/Home
mv $BACKUP_JMODS/jmods $APPLICATION_PATH/Contents/Home
fi
mv $APPLICATION_PATH $EXPLODED/$BUILD_NAME
tar -pczvf $INPUT_FILE --exclude='*.dSYM' --exclude='man' -C $EXPLODED $BUILD_NAME
tar -pczvf $INPUT_FILE --exclude='man' -C $EXPLODED $BUILD_NAME
log "Finished zipping"
)
rm -rf "$EXPLODED"

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2016, 2021, 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
@@ -88,7 +88,10 @@ $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXECUTABLE_SUFFIX) $(CLASSLIST
$(CAT) $(LINK_OPT_DIR)/stderr $(JLI_TRACE_FILE) ; \
exit $$exitcode \
)
$(GREP) -v HelloClasslist $@.raw.2 > $@
$(GREP) -v HelloClasslist $@.raw.2 > $@.raw.3
$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java \
-cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
build.tools.classlist.SortClasslist $@.raw.3 > $@
# The jli trace is created by the same recipe as classlist. By declaring these
# dependencies, make will correctly rebuild both jli trace and classlist

View File

@@ -324,7 +324,7 @@ $(eval $(call SetupTarget, vscode-project-ccls, \
# aren't built until after libjava and libjvm are available to link to.
$(eval $(call SetupTarget, demos-jdk, \
MAKEFILE := CompileDemos, \
DEPS := java.base-libs exploded-image, \
DEPS := java.base-libs exploded-image buildtools-jdk, \
))
$(eval $(call SetupTarget, test-image-demos-jdk, \
@@ -383,12 +383,12 @@ bootcycle-images:
$(eval $(call SetupTarget, zip-security, \
MAKEFILE := ZipSecurity, \
DEPS := java.base-java java.security.jgss-java java.security.jgss-libs, \
DEPS := buildtools-jdk java.base-java java.security.jgss-java java.security.jgss-libs, \
))
$(eval $(call SetupTarget, zip-source, \
MAKEFILE := ZipSource, \
DEPS := gensrc, \
DEPS := buildtools-jdk gensrc, \
))
$(eval $(call SetupTarget, jrtfs-jar, \
@@ -508,13 +508,13 @@ $(eval $(call SetupTarget, docs-jdk-index, \
$(eval $(call SetupTarget, docs-zip, \
MAKEFILE := Docs, \
TARGET := docs-zip, \
DEPS := docs-jdk, \
DEPS := docs-jdk buildtools-jdk, \
))
$(eval $(call SetupTarget, docs-specs-zip, \
MAKEFILE := Docs, \
TARGET := docs-specs-zip, \
DEPS := docs-jdk-specs, \
DEPS := docs-jdk-specs buildtools-jdk, \
))
$(eval $(call SetupTarget, update-build-docs, \

View File

@@ -80,6 +80,8 @@ TOOL_GENERATECACERTS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_class
TOOL_GENERATEEMOJIDATA = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
build.tools.generateemojidata.GenerateEmojiData
TOOL_MAKEZIPREPRODUCIBLE = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
build.tools.makezipreproducible.MakeZipReproducible
# TODO: There are references to the jdwpgen.jar in jdk/make/netbeans/jdwpgen/build.xml
# and nbproject/project.properties in the same dir. Needs to be looked at.

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2021, 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
@@ -94,11 +94,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_PATHS],
# Locate the directory of this script.
AUTOCONF_DIR=$TOPDIR/make/autoconf
# Setup username (for use in adhoc version strings etc)
# Outer [ ] to quote m4.
[ USERNAME=`$ECHO "$USER" | $TR -d -c '[a-z][A-Z][0-9]'` ]
AC_SUBST(USERNAME)
])
###############################################################################

View File

@@ -356,6 +356,14 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS],
fi
AC_SUBST(IS_GNU_TIME)
# Check if it's GNU date
check_date=`$DATE --version 2>&1 | $GREP GNU`
if test "x$check_date" != x; then
IS_GNU_DATE=yes
else
IS_GNU_DATE=no
fi
if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then
UTIL_REQUIRE_PROGS(DSYMUTIL, dsymutil)
UTIL_REQUIRE_PROGS(MIG, mig)

View File

@@ -199,6 +199,12 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS],
AC_MSG_ERROR([Copyright year must have a value])
elif test "x$with_copyright_year" != x; then
COPYRIGHT_YEAR="$with_copyright_year"
elif test "x$SOURCE_DATE_EPOCH" != x; then
if test "x$IS_GNU_DATE" = xyes; then
COPYRIGHT_YEAR=`date --date=@$SOURCE_DATE_EPOCH +%Y`
else
COPYRIGHT_YEAR=`date -j -f %s $SOURCE_DATE_EPOCH +%Y`
fi
else
COPYRIGHT_YEAR=`$DATE +'%Y'`
fi
@@ -735,7 +741,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_REPRODUCIBLE_BUILD],
if test "x$OPENJDK_BUILD_OS" = xwindows && \
test "x$ALLOW_ABSOLUTE_PATHS_IN_OUTPUT" = xfalse && \
test "x$ENABLE_REPRODUCIBLE_BUILD" = xfalse; then
AC_MSG_NOTICE([On Windows it is not possible to combine --disable-reproducible-builds])
AC_MSG_NOTICE([On Windows it is not possible to combine --disable-reproducible-build])
AC_MSG_NOTICE([with --disable-absolute-paths-in-output.])
AC_MSG_ERROR([Cannot continue])
fi

View File

@@ -69,6 +69,17 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS],
AC_SUBST(JDK_RC_PLATFORM_NAME)
AC_SUBST(HOTSPOT_VM_DISTRO)
# Setup username (for use in adhoc version strings etc)
AC_ARG_WITH([build-user], [AS_HELP_STRING([--with-build-user],
[build username to use in version strings])])
if test "x$with_build_user" != x; then
USERNAME="$with_build_user"
else
# Outer [ ] to quote m4.
[ USERNAME=`$ECHO "$USER" | $TR -d -c '[a-z][A-Z][0-9]'` ]
fi
AC_SUBST(USERNAME)
# Set the JDK RC name
AC_ARG_WITH(jdk-rc-name, [AS_HELP_STRING([--with-jdk-rc-name],
[Set JDK RC name. This is used for FileDescription and ProductName properties

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2021, 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
@@ -26,6 +26,9 @@
ifndef _ZIP_ARCHIVE_GMK
_ZIP_ARCHIVE_GMK := 1
# Depends on build tools for MakeZipReproducible
include ../ToolsJdk.gmk
ifeq (,$(_MAKEBASE_GMK))
$(error You must include MakeBase.gmk prior to including ZipArchive.gmk)
endif
@@ -51,6 +54,8 @@ endif
# FOLLOW_SYMLINKS - Set to explicitly follow symlinks. Affects performance of
# finding files.
# ZIP_OPTIONS extra options to pass to zip
# REPRODUCIBLE override ENABLE_REPRODUCIBLE_BUILD (to make zip reproducible or not)
SetupZipArchive = $(NamedParamsMacroTemplate)
define SetupZipArchiveBody
@@ -124,6 +129,10 @@ define SetupZipArchiveBody
) \
)
ifeq ($$($1_REPRODUCIBLE), )
$1_REPRODUCIBLE := $$(ENABLE_REPRODUCIBLE_BUILD)
endif
# Use a slightly shorter name for logging, but with enough path to identify this zip.
$1_NAME:=$$(subst $$(OUTPUTDIR)/,,$$($1_ZIP))
@@ -134,6 +143,8 @@ define SetupZipArchiveBody
# dir is very small.
# If zip has nothing to do, it returns 12 and would fail the build. Check for 12
# and only fail if it's not.
# For reproducible builds set the zip access & modify times to SOURCE_DATE_EPOCH
# by using a ziptmp folder to generate final zip from using MakeZipReproducible.
$$($1_ZIP) : $$($1_ALL_SRCS) $$($1_EXTRA_DEPS)
$$(call LogWarn, Updating $$($1_NAME))
$$(call MakeTargetDir)
@@ -163,7 +174,18 @@ define SetupZipArchiveBody
$$($1_ZIP_EXCLUDES_$$s) \
|| test "$$$$?" = "12" \
))$$(NEWLINE) \
) true \
) true
ifeq ($$($1_REPRODUCIBLE), true)
$$(call ExecuteWithLog, \
$$(SUPPORT_OUTPUTDIR)/makezipreproducible/$$(patsubst $$(OUTPUTDIR)/%,%, $$@), \
($(RM) $$(SUPPORT_OUTPUTDIR)/ziptmp/$1/tmp.zip && \
$(MKDIR) -p $$(SUPPORT_OUTPUTDIR)/ziptmp/$1 && \
$(TOOL_MAKEZIPREPRODUCIBLE) -f $$(SUPPORT_OUTPUTDIR)/ziptmp/$1/tmp.zip \
-t $(SOURCE_DATE_EPOCH) $$@ && \
$(RM) $$@ && \
$(MV) $$(SUPPORT_OUTPUTDIR)/ziptmp/$1/tmp.zip $$@ \
))
endif
$(TOUCH) $$@
# Add zip to target list

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2021, 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.
*/
/**
* This application is meant to be run to create a classlist file representing
* common use.
*
* The classlist is produced by adding -XX:DumpLoadedClassList=classlist
*/
package build.tools.classlist;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.Scanner;
/**
* The classlist generated by build.tools.classlist.HelloClasslist
* may have non-deterministic contents, affected by Java thread execution order.
* SortClasslist sorts the file to make the JDK image's contents more deterministic.
*/
public class SortClasslist {
public static void main(String args[]) throws FileNotFoundException {
ArrayList<String> classes = new ArrayList<>();
ArrayList<String> lambdas = new ArrayList<>();
FileInputStream fis = new FileInputStream(args[0]);
Scanner scanner = new Scanner(fis);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith("#")) {
// Comments -- print them first without sorting. These appear only at the top
// of the file.
System.out.println(line);
} else if (line.startsWith("@")) {
// @lambda-form-invoker, @lambda-proxy, etc.
lambdas.add(line);
} else {
// We should find a pattern like this:
//
// <beginning of line>java/lang/Object<end of line>
final String className = line;
classes.add(className);
}
}
Collections.sort(classes);
Collections.sort(lambdas);
for (String s : classes) {
System.out.println(s);
}
for (String s : lambdas) {
System.out.println(s);
}
}
}

View File

@@ -114,6 +114,7 @@ public class CLDRConverter {
ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT);
private static Set<String> AVAILABLE_TZIDS;
static int copyrightYear;
private static String zoneNameTempFile;
private static String tzDataDir;
private static final Map<String, String> canonicalTZMap = new HashMap<>();
@@ -217,6 +218,10 @@ public class CLDRConverter {
verbose = true;
break;
case "-year":
copyrightYear = Integer.parseInt(args[++i]);
break;
case "-zntempfile":
zoneNameTempFile = args[++i];
break;
@@ -235,7 +240,7 @@ public class CLDRConverter {
}
}
} catch (RuntimeException e) {
severe("unknown or imcomplete arg(s): " + currentArg);
severe("unknown or incomplete arg(s): " + currentArg);
usage();
System.exit(1);
}
@@ -260,6 +265,10 @@ public class CLDRConverter {
setupBaseLocales("en-US");
}
if (copyrightYear == 0) {
copyrightYear = ZonedDateTime.now(ZoneId.of("America/Los_Angeles")).getYear();
}
bundleGenerator = new ResourceBundleGenerator();
// Parse data independent of locales
@@ -292,6 +301,7 @@ public class CLDRConverter {
+ "\t-basemodule generates bundles that go into java.base module%n"
+ "\t-baselocales loc(,loc)* locales that go into the base module%n"
+ "\t-o dir output directory (default: ./build/gensrc)%n"
+ "\t-year year copyright year in output%n"
+ "\t-zntempfile template file for java.time.format.ZoneName.java%n"
+ "\t-tzdatadir tzdata directory for java.time.format.ZoneName.java%n"
+ "\t-utf8 use UTF-8 rather than \\uxxxx (for debug)%n");

View File

@@ -26,6 +26,7 @@
package build.tools.cldrconverter;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
@@ -131,8 +132,7 @@ class CopyrightHeaders {
" * questions.\n" +
" */\n";
static String getOracleCopyright() {
int year = getYear();
static String getOracleCopyright(int year) {
return String.format(year > 2012 ? ORACLE_AFTER2012 : ORACLE2012, year);
}
@@ -140,16 +140,10 @@ class CopyrightHeaders {
return UNICODE;
}
static String getOpenJDKCopyright() {
int year = getYear();
static String getOpenJDKCopyright(int year) {
return String.format(year > 2012 ? OPENJDK_AFTER2012 : OPENJDK2012, year);
}
private static int getYear() {
return new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles"),
Locale.US).get(Calendar.YEAR);
}
// no instantiation
private CopyrightHeaders() {
}

View File

@@ -198,7 +198,7 @@ class ResourceBundleGenerator implements BundleGenerator {
try (PrintWriter out = new PrintWriter(file, encoding)) {
// Output copyright headers
out.println(CopyrightHeaders.getOpenJDKCopyright());
out.println(CopyrightHeaders.getOpenJDKCopyright(CLDRConverter.copyrightYear));
out.println(CopyrightHeaders.getUnicodeCopyright());
if (useJava) {
@@ -266,7 +266,7 @@ class ResourceBundleGenerator implements BundleGenerator {
CLDRConverter.info("Generating file " + file);
try (PrintWriter out = new PrintWriter(file, "us-ascii")) {
out.printf(CopyrightHeaders.getOpenJDKCopyright());
out.printf(CopyrightHeaders.getOpenJDKCopyright(CLDRConverter.copyrightYear));
out.printf((CLDRConverter.isBaseModule ? "package sun.util.cldr;\n\n" :
"package sun.util.resources.cldr.provider;\n\n")

View File

@@ -30,13 +30,15 @@ import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.stream.Collectors;
@@ -52,17 +54,19 @@ import java.util.stream.Collectors;
public class EquivMapsGenerator {
public static void main(String[] args) throws Exception {
if (args.length != 2) {
if (args.length != 3) {
System.err.println("Usage: java EquivMapsGenerator"
+ " language-subtag-registry.txt LocaleEquivalentMaps.java");
+ " language-subtag-registry.txt LocaleEquivalentMaps.java copyrightYear");
System.exit(1);
}
copyrightYear = Integer.parseInt(args[2]);
readLSRfile(args[0]);
generateEquivalentMap();
generateSourceCode(args[1]);
}
private static String LSRrevisionDate;
private static int copyrightYear;
private static Map<String, StringBuilder> initialLanguageMap =
new TreeMap<>();
private static Map<String, StringBuilder> initialRegionVariantMap =
@@ -246,9 +250,7 @@ public class EquivMapsGenerator {
+ "}";
private static String getOpenJDKCopyright() {
int year = ZonedDateTime.now(ZoneId
.of("America/Los_Angeles")).getYear();
return String.format(Locale.US, COPYRIGHT, year);
return String.format(Locale.US, COPYRIGHT, copyrightYear);
}
/**

View File

@@ -0,0 +1,231 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.makezipreproducible;
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
* Generate a zip file in a "reproducible" manner from the input zip file.
* Standard zip tools rely on OS file list querying whose ordering can vary
* by platform architecture, this class ensures the zip entries are ordered
* and also supports SOURCE_DATE_EPOCH timestamps.
*/
public class MakeZipReproducible {
String input_file = null;
String fname = null;
String zname = "";
long timestamp = -1L;
boolean verbose = false;
// Keep a sorted Set of ZipEntrys to be processed, so that the zip is reproducible
SortedMap<String, ZipEntry> entries = new TreeMap<String, ZipEntry>();
private boolean ok;
public MakeZipReproducible() {
}
public synchronized boolean run(String args[]) {
ok = true;
if (!parseArgs(args)) {
return false;
}
try {
zname = fname.replace(File.separatorChar, '/');
if (zname.startsWith("./")) {
zname = zname.substring(2);
}
if (verbose) System.out.println("Input zip file: " + input_file);
File inFile = new File(input_file);
if (!inFile.exists()) {
error("Input zip file does not exist");
ok = false;
} else {
File zipFile = new File(fname);
// Check archive to create does not exist
if (!zipFile.exists()) {
// Process input ZipEntries
ok = processInputEntries(inFile);
if (ok) {
try (FileOutputStream out = new FileOutputStream(fname)) {
ok = create(inFile, new BufferedOutputStream(out, 4096));
}
} else {
}
} else {
error("Target zip file "+fname+" already exists.");
ok = false;
}
}
} catch (IOException e) {
fatalError(e);
ok = false;
} catch (Error ee) {
ee.printStackTrace();
ok = false;
} catch (Throwable t) {
t.printStackTrace();
ok = false;
}
return ok;
}
boolean parseArgs(String args[]) {
try {
boolean parsingIncludes = false;
boolean parsingExcludes = false;
int count = 0;
while(count < args.length) {
if (args[count].startsWith("-")) {
String flag = args[count].substring(1);
switch (flag.charAt(0)) {
case 'f':
fname = args[++count];
break;
case 't':
// SOURCE_DATE_EPOCH timestamp specified
timestamp = Long.parseLong(args[++count]) * 1000;
break;
case 'v':
verbose = true;
break;
default:
error(String.format("Illegal option -%s", String.valueOf(flag.charAt(0))));
usageError();
return false;
}
} else {
// input zip file
if (input_file != null) {
error("Input zip file already specified");
usageError();
return false;
}
input_file = args[count];
}
count++;
}
} catch (ArrayIndexOutOfBoundsException e) {
usageError();
return false;
} catch (NumberFormatException e) {
usageError();
return false;
}
if (fname == null) {
error("-f <outputArchiveName> must be specified");
usageError();
return false;
}
// If no files specified then default to current directory
if (input_file == null) {
error("No input zip file specified");
usageError();
return false;
}
return true;
}
// Process input zip file and add to sorted entries set
boolean processInputEntries(File inFile) throws IOException {
ZipFile zipFile = new ZipFile(inFile);
zipFile.stream().forEach(entry -> entries.put(entry.getName(), entry));
return true;
}
// Create new zip from entries
boolean create(File inFile, OutputStream out) throws IOException
{
try (ZipFile zipFile = new ZipFile(inFile);
ZipOutputStream zos = new ZipOutputStream(out)) {
for (Map.Entry<String, ZipEntry> entry : entries.entrySet()) {
ZipEntry zipEntry = entry.getValue();
if (zipEntry.getSize() > 0) {
try (InputStream eis = zipFile.getInputStream(zipEntry)) {
addEntry(zos, zipEntry, eis);
}
} else {
addEntry(zos, zipEntry, null);
}
}
}
return true;
}
// Add Entry and data to Zip
void addEntry(ZipOutputStream zos, ZipEntry entry, InputStream entryInputStream) throws IOException {
if (verbose) {
System.out.println("Adding: "+entry.getName());
}
// Set to specified timestamp if set otherwise leave as original lastModified time
if (timestamp != -1L) {
entry.setTime(timestamp);
}
zos.putNextEntry(entry);
if (entry.getSize() > 0 && entryInputStream != null) {
entryInputStream.transferTo(zos);
}
zos.closeEntry();
}
void usageError() {
error(
"Usage: MakeZipReproducible [-v] [-t <SOURCE_DATE_EPOCH>] -f <output_zip_file> <input_zip_file>\n" +
"Options:\n" +
" -v verbose output\n" +
" -f specify archive file name to create\n" +
" -t specific SOURCE_DATE_EPOCH value to use for timestamps\n" +
" input_zip_file re-written as a reproducible zip output_zip_file.\n");
}
void fatalError(Exception e) {
e.printStackTrace();
}
protected void error(String s) {
System.err.println(s);
}
public static void main(String args[]) {
MakeZipReproducible z = new MakeZipReproducible();
System.exit(z.run(args) ? 0 : 1);
}
}

View File

@@ -62,6 +62,7 @@ $(CLDR_GEN_DONE): $(wildcard $(CLDR_DATA_DIR)/dtd/*.dtd) \
-baselocales "en-US" \
-o $(GENSRC_DIR) \
-basemodule \
-year $(COPYRIGHT_YEAR) \
-zntempfile $(ZONENAME_TEMPLATE) \
-tzdatadir $(TZ_DATA_DIR))
$(TOUCH) $@
@@ -99,7 +100,7 @@ GENSRC_LSREQUIVMAPS := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/util/locale/Loc
$(GENSRC_LSREQUIVMAPS): $(TOPDIR)/make/data/lsrdata/language-subtag-registry.txt $(BUILD_TOOLS_JDK)
$(call MakeDir, $(@D))
$(TOOL_GENERATELSREQUIVMAPS) $< $@
$(TOOL_GENERATELSREQUIVMAPS) $< $@ $(COPYRIGHT_YEAR)
TARGETS += $(GENSRC_LSREQUIVMAPS)

View File

@@ -72,7 +72,9 @@ $(JDK_JAVADOC_DIR)/_element_lists.marker: \
$(MODULE_INFOS)
$(call MakeTargetDir)
$(call LogInfo, Creating javadoc element lists)
$(RM) -r $(ELEMENT_LISTS_DIR)
$(RM) $(ELEMENT_LISTS_DIR)/element-list-{$(call CommaList, \
$(call sequence, $(GENERATE_SYMBOLS_FROM_JDK_VERSION), \
$(JDK_SOURCE_TARGET_VERSION)))}.txt
# Generate element-list files for JDK 11 to current-1
$(call ExecuteWithLog, $@_historic, \
$(JAVA_SMALL) $(INTERIM_LANGTOOLS_ARGS) \

View File

@@ -46,6 +46,7 @@ $(CLDR_GEN_DONE): $(wildcard $(CLDR_DATA_DIR)/dtd/*.dtd) \
$(call ExecuteWithLog, $@, \
$(TOOL_CLDRCONVERTER) -base $(CLDR_DATA_DIR) \
-baselocales "en-US" \
-year $(COPYRIGHT_YEAR) \
-o $(GENSRC_DIR))
$(TOUCH) $@

View File

@@ -356,8 +356,8 @@ compare_general_files() {
"
$CAT $OTHER_DIR/$f | eval "$SVG_FILTER" > $OTHER_FILE
$CAT $THIS_DIR/$f | eval "$SVG_FILTER" > $THIS_FILE
elif [[ "$f" = *"/lib/classlist" ]] || [ "$SUFFIX" = "jar_contents" ]; then
# The classlist files may have some lines in random order
elif [ "$SUFFIX" = "jar_contents" ]; then
# The jar_contents files may have some lines in random order
OTHER_FILE=$WORK_DIR/$f.other
THIS_FILE=$WORK_DIR/$f.this
$MKDIR -p $(dirname $OTHER_FILE) $(dirname $THIS_FILE)

View File

@@ -1885,7 +1885,11 @@ int os::fork_and_exec(const char* cmd, bool prefer_vfork) {
// Use always vfork on AIX, since its safe and helps with analyzing OOM situations.
// Otherwise leave it up to the caller.
AIX_ONLY(prefer_vfork = true;)
#ifdef __APPLE__
pid = ::fork();
#else
pid = prefer_vfork ? ::vfork() : ::fork();
#endif
if (pid < 0) {
// fork failed

View File

@@ -113,10 +113,12 @@ class JfrNetworkInterfaceName : public JfrSerializer {
void serialize(JfrCheckpointWriter& writer) {} // we write each constant lazily
void on_rotation() {
for (int i = 0; i < _interfaces->length(); ++i) {
const InterfaceEntry& entry = _interfaces->at(i);
if (entry.written) {
entry.written = false;
if (_interfaces != NULL) {
for (int i = 0; i < _interfaces->length(); ++i) {
const InterfaceEntry &entry = _interfaces->at(i);
if (entry.written) {
entry.written = false;
}
}
}
}

View File

@@ -327,7 +327,7 @@ public class ModuleDescriptor
*/
@Override
public int hashCode() {
int hash = name.hashCode() * 43 + mods.hashCode();
int hash = name.hashCode() * 43 + modsHashCode(mods);
if (compiledVersion != null)
hash = hash * 43 + compiledVersion.hashCode();
if (rawCompiledVersion != null)
@@ -505,7 +505,7 @@ public class ModuleDescriptor
*/
@Override
public int hashCode() {
int hash = mods.hashCode();
int hash = modsHashCode(mods);
hash = hash * 43 + source.hashCode();
return hash * 43 + targets.hashCode();
}
@@ -708,7 +708,7 @@ public class ModuleDescriptor
*/
@Override
public int hashCode() {
int hash = mods.hashCode();
int hash = modsHashCode(mods);
hash = hash * 43 + source.hashCode();
return hash * 43 + targets.hashCode();
}
@@ -2261,7 +2261,7 @@ public class ModuleDescriptor
int hc = hash;
if (hc == 0) {
hc = name.hashCode();
hc = hc * 43 + Objects.hashCode(modifiers);
hc = hc * 43 + modsHashCode(modifiers);
hc = hc * 43 + requires.hashCode();
hc = hc * 43 + Objects.hashCode(packages);
hc = hc * 43 + exports.hashCode();
@@ -2546,6 +2546,18 @@ public class ModuleDescriptor
.collect(Collectors.joining(" "));
}
/**
* Generates and returns a hashcode for the enum instances. The returned hashcode
* is a value based on the {@link Enum#name() name} of each enum instance.
*/
private static int modsHashCode(Iterable<? extends Enum<?>> enums) {
int h = 0;
for (Enum<?> e : enums) {
h = h * 43 + Objects.hashCode(e.name());
}
return h;
}
private static <T extends Object & Comparable<? super T>>
int compare(T obj1, T obj2) {
if (obj1 != null) {

View File

@@ -46,6 +46,7 @@ import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import jdk.internal.util.StaticProperty;
import sun.nio.cs.ISO_8859_1;
import sun.nio.cs.UTF_8;
@@ -807,17 +808,25 @@ public class Properties extends Hashtable<Object,Object> {
* If the comments argument is not null, then an ASCII {@code #}
* character, the comments string, and a line separator are first written
* to the output stream. Thus, the {@code comments} can serve as an
* identifying comment. Any one of a line feed ('\n'), a carriage
* return ('\r'), or a carriage return followed immediately by a line feed
* in comments is replaced by a line separator generated by the {@code Writer}
* and if the next character in comments is not character {@code #} or
* character {@code !} then an ASCII {@code #} is written out
* after that line separator.
* identifying comment. Any one of a line feed ({@code \n}), a carriage
* return ({@code \r}), or a carriage return followed immediately by a line feed
* ({@code \r\n}) in comments is replaced by a
* {@link System#lineSeparator() line separator} and if the next
* character in comments is not character {@code #} or character {@code !} then
* an ASCII {@code #} is written out after that line separator.
* <p>
* Next, a comment line is always written, consisting of an ASCII
* {@code #} character, the current date and time (as if produced
* by the {@code toString} method of {@code Date} for the
* current time), and a line separator as generated by the {@code Writer}.
* If the {@systemProperty java.properties.date} is set on the command line
* and is non-empty (as determined by {@link String#isEmpty() String.isEmpty}),
* a comment line is written as follows.
* First, a {@code #} character is written, followed by the contents
* of the property, followed by a line separator. Any line terminator characters
* in the value of the system property are treated the same way as noted above
* for the comments argument.
* If the system property is not set or is empty, a comment line is written
* as follows.
* First, a {@code #} character is written, followed by the current date and time
* formatted as if by the {@link Date#toString() Date.toString} method,
* followed by a line separator.
* <p>
* Then every entry in this {@code Properties} table is
* written out, one per line. For each entry the key string is
@@ -833,6 +842,10 @@ public class Properties extends Hashtable<Object,Object> {
* After the entries have been written, the output stream is flushed.
* The output stream remains open after this method returns.
*
* @implSpec The keys and elements are written in the natural sort order
* of the keys in the {@code entrySet()} unless {@code entrySet()} is
* overridden by a subclass to return a different value than {@code super.entrySet()}.
*
* @param writer an output character stream writer.
* @param comments a description of the property list.
* @throws IOException if writing this property list to the specified
@@ -903,12 +916,25 @@ public class Properties extends Hashtable<Object,Object> {
if (comments != null) {
writeComments(bw, comments);
}
bw.write("#" + new Date().toString());
bw.newLine();
writeDateComment(bw);
synchronized (this) {
for (Map.Entry<Object, Object> e : entrySet()) {
String key = (String)e.getKey();
String val = (String)e.getValue();
@SuppressWarnings("unchecked")
Collection<Map.Entry<String, String>> entries = (Set<Map.Entry<String, String>>) (Set) entrySet();
// entrySet() can be overridden by subclasses. Here we check to see if
// the returned instance type is the one returned by the Properties.entrySet()
// implementation. If yes, then we sort those entries in the natural order
// of their key. Else, we consider that the subclassed implementation may
// potentially have returned a differently ordered entries and so we just
// use the iteration order of the returned instance.
if (entries instanceof Collections.SynchronizedSet<?> ss
&& ss.c instanceof EntrySet) {
entries = new ArrayList<>(entries);
((List<Map.Entry<String, String>>) entries).sort(Map.Entry.comparingByKey());
}
for (Map.Entry<String, String> e : entries) {
String key = e.getKey();
String val = e.getValue();
key = saveConvert(key, true, escUnicode);
/* No need to escape embedded and trailing spaces for value, hence
* pass false to flag.
@@ -921,6 +947,19 @@ public class Properties extends Hashtable<Object,Object> {
bw.flush();
}
private static void writeDateComment(BufferedWriter bw) throws IOException {
// value of java.properties.date system property isn't sensitive
// and so doesn't need any security manager checks to make the value accessible
// to the callers
String sysPropVal = StaticProperty.javaPropertiesDate();
if (sysPropVal != null && !sysPropVal.isEmpty()) {
writeComments(bw, sysPropVal);
} else {
bw.write("#" + new Date());
bw.newLine();
}
}
/**
* Loads all of the properties represented by the XML document on the
* specified input stream into this properties table.

View File

@@ -50,6 +50,7 @@ public final class StaticProperty {
private static final String JDK_SERIAL_FILTER_FACTORY;
private static final String JAVA_IO_TMPDIR;
private static final String NATIVE_ENCODING;
private static final String JAVA_PROPERTIES_DATE;
private StaticProperty() {}
@@ -65,6 +66,7 @@ public final class StaticProperty {
JDK_SERIAL_FILTER = getProperty(props, "jdk.serialFilter", null);
JDK_SERIAL_FILTER_FACTORY = getProperty(props, "jdk.serialFilterFactory", null);
NATIVE_ENCODING = getProperty(props, "native.encoding");
JAVA_PROPERTIES_DATE = getProperty(props, "java.properties.date", null);
}
private static String getProperty(Properties props, String key) {
@@ -212,4 +214,16 @@ public final class StaticProperty {
public static String nativeEncoding() {
return NATIVE_ENCODING;
}
/**
* Return the {@code java.properties.date} system property.
*
* <strong>{@link SecurityManager#checkPropertyAccess} is NOT checked
* in this method.</strong>
*
* @return the {@code java.properties.date} system property
*/
public static String javaPropertiesDate() {
return JAVA_PROPERTIES_DATE;
}
}

View File

@@ -139,6 +139,8 @@ class UnixDomainSockets {
return UnixDomainSocketAddress.of(path);
} catch (InvalidPathException e) {
throw new BindException("Invalid temporary directory");
} catch (IllegalArgumentException e) {
throw new UnsupportedOperationException("Unix Domain Sockets not supported on non-default file system");
}
}

View File

@@ -444,7 +444,8 @@ static int copystrings(char *buf, int offset, const char * const *arg) {
__attribute_noinline__
#endif
/* vfork(2) is deprecated on Solaris */
/* vfork(2) is deprecated on Darwin */
#ifndef __APPLE__
static pid_t
vforkChild(ChildStuff *c) {
volatile pid_t resultPid;
@@ -463,6 +464,7 @@ vforkChild(ChildStuff *c) {
assert(resultPid != 0); /* childProcess never returns */
return resultPid;
}
#endif
static pid_t
forkChild(ChildStuff *c) {
@@ -573,9 +575,11 @@ spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath)
static pid_t
startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
switch (c->mode) {
/* vfork(2) is deprecated on Solaris */
/* vfork(2) is deprecated on Darwin*/
#ifndef __APPLE__
case MODE_VFORK:
return vforkChild(c);
#endif
case MODE_FORK:
return forkChild(c);
case MODE_POSIX_SPAWN:

View File

@@ -43,6 +43,7 @@ final class GestureHandler {
@Native static final int ROTATE = 2;
@Native static final int MAGNIFY = 3;
@Native static final int SWIPE = 4;
@Native static final int PRESSURE = 5;
// installs a private instance of GestureHandler, if necessary
static void addGestureListenerTo(final JComponent component, final GestureListener listener) {
@@ -97,6 +98,9 @@ final class GestureHandler {
case SWIPE:
firstNotifier.recursivelyHandleSwipe(a, b, new SwipeEvent());
return;
case PRESSURE:
firstNotifier.recursivelyHandlePressure(new PressureEvent(a,b));
return;
}
}
});
@@ -107,6 +111,7 @@ final class GestureHandler {
final List<RotationListener> rotaters = new LinkedList<RotationListener>();
final List<MagnificationListener> magnifiers = new LinkedList<MagnificationListener>();
final List<SwipeListener> swipers = new LinkedList<SwipeListener>();
final List<PressureListener> pressures = new LinkedList<PressureListener>();
GestureHandler() { }
@@ -115,6 +120,7 @@ final class GestureHandler {
if (listener instanceof RotationListener) rotaters.add((RotationListener)listener);
if (listener instanceof MagnificationListener) magnifiers.add((MagnificationListener)listener);
if (listener instanceof SwipeListener) swipers.add((SwipeListener)listener);
if (listener instanceof PressureListener) pressures.add((PressureListener)listener);
}
void removeListener(final GestureListener listener) {
@@ -169,6 +175,16 @@ final class GestureHandler {
if (next != null) next.recursivelyHandleMagnify(e);
}
void recursivelyHandlePressure(final PressureEvent e) {
for (final PressureListener listener : handler.pressures) {
listener.pressure(e);
if (e.isConsumed()) return;
}
final PerComponentNotifier next = getNextNotifierForComponent(component.getParent());
if (next != null) next.recursivelyHandlePressure(e);
}
void recursivelyHandleSwipe(final double x, final double y, final SwipeEvent e) {
for (final SwipeListener listener : handler.swipers) {
if (x < 0) listener.swipedLeft(e);

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2011, 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 com.apple.eawt.event;
/**
* Event indicating a swipe was performed by the user.
*
* @see PressureListener
*
* @since Java for Mac OS X 10.10 Update 3, JDK 8
*/
public class PressureEvent extends GestureEvent {
public double getPressure() {
return pressure;
}
public double getStage() {
return stage;
}
private double pressure;
private double stage;
PressureEvent(double pressure, double stage) {
this.pressure = pressure;
this.stage = stage;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2011, 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 com.apple.eawt.event;
/**
* Listener interface for receiving pressure events.
*
* @see PressureEvent
* @see GestureUtilities
*
* @since Java for Mac OS X 10.5 Update 7, Java for Mac OS X 10.6 Update 2
*/
public interface PressureListener extends GestureListener {
public void pressure(final PressureEvent e);
}

View File

@@ -128,12 +128,8 @@ public class CCharToGlyphMapper extends CharToGlyphMapper {
};
}
// This mapper returns either the glyph code, or if the character can be
// replaced on-the-fly using CoreText substitution; the negative unicode
// value. If this "glyph code int" is treated as an opaque code, it will
// strike and measure exactly as a real glyph code - whether the character
// is present or not. Missing characters for any font on the system will
// be returned as 0, as the getMissingGlyphCode() function above indicates.
// Missing characters for any font on the system will be returned as 0,
// as the getMissingGlyphCode() function above indicates.
private static native void nativeCharsToGlyphs(final long nativeFontPtr,
int count, char[] unicodes,
int[] glyphs);

View File

@@ -1,81 +0,0 @@
/*
* Copyright 2000-2018 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sun.font;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;
public final class CCompositeFont extends CompositeFont {
private final List<CFont> fallbackFonts = new ArrayList<>();
public CCompositeFont(CFont font) {
super(new PhysicalFont[]{font});
mapper = new CCompositeGlyphMapper(this);
}
@Override
public synchronized int getNumSlots() {
return super.getNumSlots();
}
@Override
public CFont getSlotFont(int slot) {
if (slot == 0) return (CFont) super.getSlotFont(0);
synchronized (this) {
return fallbackFonts.get(slot - 1);
}
}
@Override
synchronized FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
return super.getStrike(desc, copy);
}
@Override
protected synchronized int getValidatedGlyphCode(int glyphCode) {
return super.getValidatedGlyphCode(glyphCode);
}
@Override
public boolean hasSupplementaryChars() {
return false;
}
@Override
public boolean useAAForPtSize(int ptsize) {
return true;
}
public synchronized int findSlot(String fontName) {
for (int slot = 0; slot < numSlots; slot++) {
CFont slotFont = getSlotFont(slot);
if (fontName.equals(slotFont.getNativeFontName())) {
return slot;
}
}
return -1;
}
public synchronized int addSlot(CFont font) {
int slot = findSlot(font.getNativeFontName());
if (slot >= 0) return slot;
fallbackFonts.add(font);
lastFontStrike = new SoftReference<>(null);
strikeCache.clear();
return numSlots++;
}
}

View File

@@ -1,79 +0,0 @@
/*
* Copyright (c) 2015, 2018, 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.font;
import java.awt.*;
public final class CCompositeGlyphMapper extends CompositeGlyphMapper {
public CCompositeGlyphMapper(CCompositeFont compFont) {
super(compFont);
}
@Override
protected int convertToGlyph(int unicode) {
CCompositeFont compositeFont = (CCompositeFont) font;
CFont mainFont = (CFont) font.getSlotFont(0);
String[] fallbackFontInfo = new String[2];
int glyphCode = nativeCodePointToGlyph(mainFont.getNativeFontPtr(), unicode, fallbackFontInfo);
if (glyphCode == missingGlyph) {
setCachedGlyphCode(unicode, missingGlyph);
return missingGlyph;
}
String fallbackFontName = fallbackFontInfo[0];
String fallbackFontFamilyName = fallbackFontInfo[1];
if (fallbackFontName == null || fallbackFontFamilyName == null) {
int result = compositeGlyphCode(0, glyphCode);
setCachedGlyphCode(unicode, result);
return result;
}
int slot = compositeFont.findSlot(fallbackFontName);
if (slot < 0) {
Font2D fallbackFont = FontManagerFactory.getInstance().findFont2D(fallbackFontName,
Font.PLAIN, FontManager.NO_FALLBACK);
if (!(fallbackFont instanceof CFont) ||
!fallbackFontName.equals(((CFont) fallbackFont).getNativeFontName())) {
// Native font fallback mechanism can return "hidden" fonts - their names start with dot,
// and they are not returned in a list of fonts available in system, but they can still be used
// if requested explicitly.
fallbackFont = new CFont(fallbackFontName, fallbackFontFamilyName, null);
}
if (mainFont.isFakeItalic()) fallbackFont = ((CFont)fallbackFont).createItalicVariant(false);
slot = compositeFont.addSlot((CFont) fallbackFont);
}
int result = compositeGlyphCode(slot, glyphCode);
setCachedGlyphCode(unicode, result);
return result;
}
// This invokes native font fallback mechanism, returning information about font (its Postscript and family names)
// able to display a given character, and corresponding glyph code
private static native int nativeCodePointToGlyph(long nativeFontPtr, int codePoint, String[] result);
}

View File

@@ -31,6 +31,9 @@ import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Set;
// Right now this class is final to avoid a problem with native code.
// For some reason the JNI IsInstanceOf was not working correctly
@@ -175,14 +178,12 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW
isFakeItalic = other.isFakeItalic;
}
public CFont createItalicVariant(boolean updateStyle) {
public CFont createItalicVariant() {
CFont font = new CFont(this, familyName);
font.nativeFontName = fullName;
font.fullName =
fullName + (style == Font.BOLD ? "" : "-") + "Italic-Derived";
if (updateStyle) {
font.style |= Font.ITALIC;
}
font.style |= Font.ITALIC;
font.isFakeItalic = true;
return font;
}
@@ -204,11 +205,51 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW
return getCGFontPtrNative(getNativeFontPtr());
}
static native void getCascadeList(long nativeFontPtr, ArrayList<String> listOfString);
private CompositeFont createCompositeFont() {
ArrayList<String> listOfString = new ArrayList<String>();
getCascadeList(getNativeFontPtr(), listOfString);
Set<String> components = new LinkedHashSet<>(listOfString);
// In some italic cases the standard Mac cascade list is missing Arabic.
components.add("GeezaPro");
CFontManager fm = (CFontManager) FontManagerFactory.getInstance();
components.addAll(fm.getAdditionalFallbackVariants());
int numFonts = 1 + components.size();
PhysicalFont[] fonts = new PhysicalFont[numFonts];
fonts[0] = this;
int idx = 1;
if (FontUtilities.isLogging()) {
FontUtilities.logInfo("Cascading list for " + this + " :");
}
for (String s : components) {
if (FontUtilities.isLogging()) {
FontUtilities.logInfo("Fallback:" + s);
}
if (s.equals(".AppleSymbolsFB")) {
// Don't know why we get the weird name above .. replace.
s = "AppleSymbols";
}
Font2D f2d = fm.getOrCreateFallbackFont(s);
if (f2d == null || f2d == this) {
continue;
}
fonts[idx++] = (PhysicalFont)f2d;
}
if (idx < fonts.length) {
PhysicalFont[] orig = fonts;
fonts = new PhysicalFont[idx];
System.arraycopy(orig, 0, fonts, 0, idx);
}
return new CompositeFont(fonts);
}
private CompositeFont compFont;
public CompositeFont getCompositeFont2D() {
if (compFont == null) {
compFont = new CCompositeFont(this);
compFont = createCompositeFont();
}
return compFont;
}
@@ -236,14 +277,6 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW
return new CStrike(this, desc);
}
boolean isFakeItalic() {
return isFakeItalic;
}
String getNativeFontName() {
return nativeFontName;
}
@Override
public String getTypographicSubfamilyName() {
return faceName == null ? super.getTypographicSubfamilyName() : faceName;
@@ -276,8 +309,4 @@ public final class CFont extends PhysicalFont implements FontSubstitution, FontW
", familyName: " + familyName + ", style: " + style +
" } aka: " + super.toString();
}
public Font2D createItalic() {
return this.createItalicVariant(true);
}
}

View File

@@ -30,20 +30,27 @@ import java.io.File;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.plaf.FontUIResource;
import sun.awt.FontConfiguration;
import sun.awt.HeadlessToolkit;
import sun.lwawt.macosx.*;
import sun.security.action.GetBooleanAction;
import sun.util.logging.PlatformLogger;
public final class CFontManager extends SunFontManager {
private static Hashtable<String, Font2D> genericFonts = new Hashtable<String, Font2D>();
private final Map<String, Font2D> fallbackFonts = new ConcurrentHashMap<>();
private final List<String> extFallbackVariants = new ArrayList<>();
@Override
protected FontConfiguration createFontConfiguration() {
@@ -230,6 +237,7 @@ public final class CFontManager extends SunFontManager {
public Object run() {
if (!loadedAllFonts) {
loadNativeFonts();
collectAdditionalFallbackVariants();
loadedAllFonts = true;
}
return null;
@@ -337,4 +345,40 @@ public final class CFontManager extends SunFontManager {
@Override
protected void populateFontFileNameMap(HashMap<String, String> fontToFileMap, HashMap<String, String> fontToFamilyNameMap,
HashMap<String, ArrayList<String>> familyToFontListMap, Locale locale) {}
@SuppressWarnings("removal")
private void collectAdditionalFallbackVariants() {
if (AccessController.doPrivileged(new GetBooleanAction("mac.ext.font.fallback"))) {
for (String fontName : genericFonts.keySet()) {
boolean accept = false;
if (fontName.equals("ArialUnicodeMS")) {
accept = true;
} else if (fontName.startsWith("NotoSans")) {
int pos = fontName.indexOf('-');
accept = pos == -1 || fontName.substring(pos + 1).equals("Regular");
}
if (accept) {
extFallbackVariants.add(fontName);
}
}
Collections.sort(extFallbackVariants); // ensure predictable order
}
}
List<String> getAdditionalFallbackVariants() {
return extFallbackVariants;
}
Font2D getOrCreateFallbackFont(String fontName) {
Font2D font2D = findFont2D(fontName, Font.PLAIN, FontManager.NO_FALLBACK);
if (font2D != null || fontName.startsWith(".")) {
return font2D;
} else {
// macOS doesn't list some system fonts in [NSFontManager availableFontFamilies] output,
// so they are not registered in font manager as part of 'loadNativeFonts'.
// These fonts are present in [NSFontManager availableFonts] output though,
// and can be accessed in the same way as other system fonts.
return fallbackFonts.computeIfAbsent(fontName, name -> new CFont(name, null, null));
}
}
}

View File

@@ -358,18 +358,14 @@ public final class CStrike extends PhysicalStrike {
}
}
// This class stores glyph pointers, and is indexed based on glyph codes,
// and negative unicode values. See the comments in
// CCharToGlyphMapper for more details on our glyph code strategy.
// This class stores glyph pointers, and is indexed based on glyph codes.
private static class GlyphInfoCache extends CStrikeDisposer {
private static final int FIRST_LAYER_SIZE = 256;
private static final int SECOND_LAYER_SIZE = 16384; // 16384 = 128x128
// rdar://problem/5204197
private final AtomicBoolean disposed = new AtomicBoolean(false);
private final long[] firstLayerCache;
private SparseBitShiftingTwoLayerArray secondLayerCache;
private HashMap<Integer, Long> generalCache;
GlyphInfoCache(final Font2D nativeFont, final FontStrikeDesc desc) {
@@ -378,19 +374,9 @@ public final class CStrike extends PhysicalStrike {
}
public synchronized long get(final int index) {
if (index < 0) {
if (-index < SECOND_LAYER_SIZE) {
// catch common unicodes
if (secondLayerCache == null) {
return 0L;
}
return secondLayerCache.get(-index);
}
} else {
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
return firstLayerCache[index];
}
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
return firstLayerCache[index];
}
if (generalCache == null) {
@@ -404,21 +390,10 @@ public final class CStrike extends PhysicalStrike {
}
public synchronized void put(final int index, final long value) {
if (index < 0) {
if (-index < SECOND_LAYER_SIZE) {
// catch common unicodes
if (secondLayerCache == null) {
secondLayerCache = new SparseBitShiftingTwoLayerArray(SECOND_LAYER_SIZE, 7); // 128x128
}
secondLayerCache.put(-index, value);
return;
}
} else {
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
firstLayerCache[index] = value;
return;
}
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
firstLayerCache[index] = value;
return;
}
if (generalCache == null) {
@@ -441,14 +416,6 @@ public final class CStrike extends PhysicalStrike {
// clean out the first array
disposeLongArray(firstLayerCache);
// clean out the two layer arrays
if (secondLayerCache != null) {
final long[][] secondLayerLongArrayArray = secondLayerCache.cache;
for (final long[] longArray : secondLayerLongArrayArray) {
if (longArray != null) disposeLongArray(longArray);
}
}
// clean up everyone else
if (generalCache != null) {
for (Long aLong : generalCache.values()) {
@@ -485,56 +452,18 @@ public final class CStrike extends PhysicalStrike {
}
}
}
private static class SparseBitShiftingTwoLayerArray {
final long[][] cache;
final int shift;
final int secondLayerLength;
SparseBitShiftingTwoLayerArray(final int size, final int shift) {
this.shift = shift;
this.cache = new long[1 << shift][];
this.secondLayerLength = size >> shift;
}
public long get(final int index) {
final int firstIndex = index >> shift;
final long[] firstLayerRow = cache[firstIndex];
if (firstLayerRow == null) return 0L;
return firstLayerRow[index - (firstIndex * (1 << shift))];
}
public void put(final int index, final long value) {
final int firstIndex = index >> shift;
long[] firstLayerRow = cache[firstIndex];
if (firstLayerRow == null) {
cache[firstIndex] = firstLayerRow = new long[secondLayerLength];
}
firstLayerRow[index - (firstIndex * (1 << shift))] = value;
}
}
}
private static class GlyphAdvanceCache {
private static final int FIRST_LAYER_SIZE = 256;
private static final int SECOND_LAYER_SIZE = 16384; // 16384 = 128x128
private final float[] firstLayerCache = new float[FIRST_LAYER_SIZE];
private SparseBitShiftingTwoLayerArray secondLayerCache;
private HashMap<Integer, Float> generalCache;
public synchronized float get(final int index) {
if (index < 0) {
if (-index < SECOND_LAYER_SIZE) {
// catch common unicodes
if (secondLayerCache == null) return 0;
return secondLayerCache.get(-index);
}
} else {
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
return firstLayerCache[index];
}
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
return firstLayerCache[index];
}
if (generalCache == null) return 0;
@@ -544,21 +473,10 @@ public final class CStrike extends PhysicalStrike {
}
public synchronized void put(final int index, final float value) {
if (index < 0) {
if (-index < SECOND_LAYER_SIZE) {
// catch common unicodes
if (secondLayerCache == null) {
secondLayerCache = new SparseBitShiftingTwoLayerArray(SECOND_LAYER_SIZE, 7); // 128x128
}
secondLayerCache.put(-index, value);
return;
}
} else {
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
firstLayerCache[index] = value;
return;
}
if (index < FIRST_LAYER_SIZE) {
// catch common glyphcodes
firstLayerCache[index] = value;
return;
}
if (generalCache == null) {
@@ -567,34 +485,5 @@ public final class CStrike extends PhysicalStrike {
generalCache.put(Integer.valueOf(index), Float.valueOf(value));
}
private static class SparseBitShiftingTwoLayerArray {
final float[][] cache;
final int shift;
final int secondLayerLength;
SparseBitShiftingTwoLayerArray(final int size, final int shift) {
this.shift = shift;
this.cache = new float[1 << shift][];
this.secondLayerLength = size >> shift;
}
public float get(final int index) {
final int firstIndex = index >> shift;
final float[] firstLayerRow = cache[firstIndex];
if (firstLayerRow == null) return 0L;
return firstLayerRow[index - (firstIndex * (1 << shift))];
}
public void put(final int index, final float value) {
final int firstIndex = index >> shift;
float[] firstLayerRow = cache[firstIndex];
if (firstLayerRow == null) {
cache[firstIndex] = firstLayerRow =
new float[secondLayerLength];
}
firstLayerRow[index - (firstIndex * (1 << shift))] = value;
}
}
}
}

View File

@@ -25,13 +25,14 @@
package sun.lwawt.macosx;
import java.awt.Component;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.security.PrivilegedAction;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.swing.JTabbedPane;
import javax.swing.*;
import static javax.accessibility.AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY;
import static javax.accessibility.AccessibleContext.ACCESSIBLE_CARET_PROPERTY;
@@ -48,6 +49,20 @@ import sun.awt.AWTAccessor;
class CAccessible extends CFRetainedResource implements Accessible {
private static Timer timer = null;
private final static int SELECTED_CHILDREN_MILLISECONDS_DEFAULT = 100;
private static int SELECTED_CHILDREN_MILLISECONDS;
static {
@SuppressWarnings("removal") int scms = java.security.AccessController.doPrivileged(new PrivilegedAction<Integer>() {
@Override
public Integer run() {
return Integer.getInteger("sun.lwawt.macosx.CAccessible.selectedChildrenMilliSeconds",
SELECTED_CHILDREN_MILLISECONDS_DEFAULT);
}
});
SELECTED_CHILDREN_MILLISECONDS = scms >= 0 ? scms : SELECTED_CHILDREN_MILLISECONDS_DEFAULT;
}
public static CAccessible getCAccessible(final Accessible a) {
if (a == null) return null;
@@ -112,19 +127,25 @@ class CAccessible extends CFRetainedResource implements Accessible {
@Override
public void propertyChange(PropertyChangeEvent e) {
assert EventQueue.isDispatchThread();
String name = e.getPropertyName();
if ( ptr != 0 ) {
Object newValue = e.getNewValue();
Object oldValue = e.getOldValue();
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_TABLE_MODEL_CHANGED) == 0) {
valueChanged(ptr);
} else if (name.compareTo(ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY) == 0 ) {
if (name.equals(ACCESSIBLE_CARET_PROPERTY)) {
execute(ptr -> selectedTextChanged(ptr));
} else if (name.equals(ACCESSIBLE_TEXT_PROPERTY)) {
execute(ptr -> valueChanged(ptr));
} else if (name.equals(ACCESSIBLE_SELECTION_PROPERTY)) {
if (timer != null) {
timer.stop();
}
timer = new Timer(SELECTED_CHILDREN_MILLISECONDS, actionEvent -> execute(ptr -> selectionChanged(ptr)));
timer.setRepeats(false);
timer.start();
} else if (name.equals(ACCESSIBLE_TABLE_MODEL_CHANGED)) {
execute(ptr -> valueChanged(ptr));
} else if (name.equals(ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY)) {
if (newValue == null || newValue instanceof AccessibleContext) {
activeDescendant = (AccessibleContext)newValue;
if (newValue instanceof Accessible) {
@@ -135,7 +156,7 @@ class CAccessible extends CFRetainedResource implements Accessible {
if (p != null) {
AccessibleContext pac = p.getAccessibleContext();
if ((pac != null) && (pac.getAccessibleRole() == AccessibleRole.TABLE)) {
selectedCellsChanged(ptr);
execute(ptr -> selectedCellsChanged(ptr));
}
}
}
@@ -151,9 +172,9 @@ class CAccessible extends CFRetainedResource implements Accessible {
}
if (newValue == AccessibleState.EXPANDED) {
treeNodeExpanded(ptr);
execute(ptr -> treeNodeExpanded(ptr));
} else if (newValue == AccessibleState.COLLAPSED) {
treeNodeCollapsed(ptr);
execute(ptr -> treeNodeCollapsed(ptr));
}
// At least for now don't handle combo box menu state changes.
@@ -161,41 +182,44 @@ class CAccessible extends CFRetainedResource implements Accessible {
// exist for combo boxes, but for now the following is only
// for JPopupMenus, not for combobox menus.
if (thisRole == AccessibleRole.COMBO_BOX) {
selectionChanged(ptr);
if (timer != null) {
timer.stop();
}
timer = new Timer(SELECTED_CHILDREN_MILLISECONDS, actionEvent -> execute(ptr -> selectionChanged(ptr)));
timer.setRepeats(false);
timer.start();
}
// if (parentRole != AccessibleRole.COMBO_BOX) {
if (thisRole == AccessibleRole.POPUP_MENU) {
if ( newValue != null &&
((AccessibleState)newValue) == AccessibleState.VISIBLE ) {
menuOpened(ptr);
} else if ( oldValue != null &&
((AccessibleState)oldValue) == AccessibleState.VISIBLE ) {
menuClosed(ptr);
}
} else if (thisRole == AccessibleRole.MENU_ITEM) {
if ( newValue != null &&
((AccessibleState)newValue) == AccessibleState.FOCUSED ) {
menuItemSelected(ptr);
}
// }
if (thisRole == AccessibleRole.POPUP_MENU) {
if (newValue != null &&
((AccessibleState) newValue) == AccessibleState.VISIBLE) {
execute(ptr -> menuOpened(ptr));
} else if (oldValue != null &&
((AccessibleState) oldValue) == AccessibleState.VISIBLE) {
execute(ptr -> menuClosed(ptr));
}
} else if (thisRole == AccessibleRole.MENU_ITEM) {
if (newValue != null &&
((AccessibleState) newValue) == AccessibleState.FOCUSED) {
execute(ptr -> menuItemSelected(ptr));
}
}
// Do send check box state changes to native side
if (thisRole == AccessibleRole.CHECK_BOX) {
valueChanged(ptr);
execute(ptr -> valueChanged(ptr));
}
} else if (name.compareTo(ACCESSIBLE_NAME_PROPERTY) == 0) {
//for now trigger only for JTabbedPane.
if (e.getSource() instanceof JTabbedPane) {
titleChanged(ptr);
execute(ptr -> titleChanged(ptr));
}
} else if (name.compareTo(ACCESSIBLE_VALUE_PROPERTY) == 0) {
AccessibleRole thisRole = accessible.getAccessibleContext()
.getAccessibleRole();
if (thisRole == AccessibleRole.SLIDER ||
thisRole == AccessibleRole.PROGRESS_BAR) {
valueChanged(ptr);
execute(ptr -> valueChanged(ptr));
}
}
}

View File

@@ -231,6 +231,15 @@ AWT_NS_WINDOW_IMPLEMENTATION
b:[event deltaY]];
}
- (void)pressureChangeWithEvent:(NSEvent *)event {
float pressure = event.pressure;
[self postGesture:event
as:com_apple_eawt_event_GestureHandler_PRESSURE
a:pressure
b:(([event respondsToSelector:@selector(stage)]) ? ((NSInteger)[event stage]) : -1)
];
}
- (void)moveTabToNewWindow:(id)sender {
AWT_ASSERT_APPKIT_THREAD;

View File

@@ -125,11 +125,35 @@ canChooseDirectories:(BOOL)inChooseDirectories
}
[thePanel setDelegate:self];
NSMenuItem *editMenuItem = nil;
NSMenu *menu = [NSApp mainMenu];
if (menu != nil) {
if (menu.numberOfItems > 0) {
NSMenu *submenu = [[menu itemAtIndex:0] submenu];
if (submenu != nil) {
menu = submenu;
}
}
editMenuItem = [self createEditMenu];
if (menu.numberOfItems > 0) {
[menu insertItem:editMenuItem atIndex:0];
} else {
[menu addItem:editMenuItem];
}
[editMenuItem release];
}
fPanelResult = [thePanel runModalForDirectory:fDirectory file:fFile];
[thePanel setDelegate:nil];
CMenuBar *menuBar = [[ApplicationDelegate sharedDelegate] defaultMenuBar];
[CMenuBar activate:menuBar modallyDisabled:NO];
if (editMenuItem != nil) {
[menu removeItem:editMenuItem];
}
if ([self userClickedOK]) {
if (fMode == java_awt_FileDialog_LOAD) {
NSOpenPanel *openPanel = (NSOpenPanel *)thePanel;
@@ -144,6 +168,33 @@ canChooseDirectories:(BOOL)inChooseDirectories
[self disposer];
}
- (NSMenuItem *) createEditMenu {
NSMenu *editMenu = [[NSMenu alloc] initWithTitle:@"Edit"];
NSMenuItem *cutItem = [[NSMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:) keyEquivalent:@"x"];
[editMenu addItem:cutItem];
[cutItem release];
NSMenuItem *copyItem = [[NSMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"c"];
[editMenu addItem:copyItem];
[copyItem release];
NSMenuItem *pasteItem = [[NSMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:) keyEquivalent:@"v"];
[editMenu addItem:pasteItem];
[pasteItem release];
NSMenuItem *selectAllItem = [[NSMenuItem alloc] initWithTitle:@"Select All" action:@selector(selectAll:) keyEquivalent:@"a"];
[editMenu addItem:selectAllItem];
[selectAllItem release];
NSMenuItem *editMenuItem = [NSMenuItem new];
[editMenuItem setTitle:@"Edit"];
[editMenuItem setSubmenu:editMenu];
[editMenu release];
return editMenuItem;
}
- (BOOL) askFilenameFilter:(NSString *)filename {
JNIEnv *env = [ThreadUtilities getJNIEnv];
jstring jString = NormalizedPathJavaStringFromNSString(env, filename);

View File

@@ -41,51 +41,6 @@ static const CGAffineTransform sInverseTX = { 1, 0, 0, -1, 0, 0 };
#pragma mark --- CoreText Support ---
// Translates a Unicode into a CGGlyph/CTFontRef pair
// Returns the substituted font, and places the appropriate glyph into "glyphRef"
CTFontRef JavaCT_CopyCTFallbackFontAndGlyphForUnicode
(const AWTFont *font, const UTF16Char *charRef, CGGlyph *glyphRef, int count) {
CTFontRef fallback = JRSFontCreateFallbackFontForCharacters((CTFontRef)font->fFont, charRef, count);
if (fallback == NULL)
{
// use the original font if we somehow got duped into trying to fallback something we can't
fallback = (CTFontRef)font->fFont;
CFRetain(fallback);
}
CTFontGetGlyphsForCharacters(fallback, charRef, glyphRef, count);
return fallback;
}
// Translates a Java glyph code int (might be a negative unicode value) into a CGGlyph/CTFontRef pair
// Returns the substituted font, and places the appropriate glyph into "glyph"
CTFontRef JavaCT_CopyCTFallbackFontAndGlyphForJavaGlyphCode
(const AWTFont *font, const jint glyphCode, CGGlyph *glyphRef)
{
// negative glyph codes are really unicodes, which were placed there by the mapper
// to indicate we should use CoreText to substitute the character
if (glyphCode >= 0)
{
*glyphRef = glyphCode;
CFRetain(font->fFont);
return (CTFontRef)font->fFont;
}
UTF16Char character = -glyphCode;
return JavaCT_CopyCTFallbackFontAndGlyphForUnicode(font, &character, glyphRef, 1);
}
// Breakup a 32 bit unicode value into the component surrogate pairs
void JavaCT_BreakupUnicodeIntoSurrogatePairs(int uniChar, UTF16Char charRef[]) {
int value = uniChar - 0x10000;
UTF16Char low_surrogate = (value & 0x3FF) | LO_SURROGATE_START;
UTF16Char high_surrogate = (((int)(value & 0xFFC00)) >> 10) | HI_SURROGATE_START;
charRef[0] = high_surrogate;
charRef[1] = low_surrogate;
}
/*
* Callback for CoreText which uses the CoreTextProviderStruct to feed CT UniChars
* We only use it for one-off lines, and don't attempt to fragment our strings
@@ -129,7 +84,7 @@ static NSDictionary* ctsDictionaryFor(const NSFont *font, BOOL useFractionalMetr
// Itterates though each glyph, and if a transform is present for that glyph, apply it to the CGContext, and strike the glyph.
// If there is no per-glyph transform, just strike the glyph. Advances must also be transformed on-the-spot as well.
void JavaCT_DrawGlyphVector
(const QuartzSDOps *qsdo, const AWTStrike *strike, const BOOL useSubstituion, const int uniChars[], const CGGlyph glyphs[], CGSize advances[], const jint g_gvTXIndicesAsInts[], const jdouble g_gvTransformsAsDoubles[], const CFIndex length)
(const QuartzSDOps *qsdo, const AWTStrike *strike, const CGGlyph glyphs[], CGSize advances[], const jint g_gvTXIndicesAsInts[], const jdouble g_gvTransformsAsDoubles[], const CFIndex length)
{
CGPoint pt = { 0, 0 };
@@ -137,49 +92,12 @@ void JavaCT_DrawGlyphVector
CGContextRef cgRef = qsdo->cgRef;
CGAffineTransform ctmText = CGContextGetTextMatrix(cgRef);
BOOL saved = false;
CGAffineTransform invTx = CGAffineTransformInvert(strike->fTx);
NSInteger i;
for (i = 0; i < length; i++)
{
CGGlyph glyph = glyphs[i];
int uniChar = uniChars[i];
// if we found a unichar instead of a glyph code, get the fallback font,
// find the glyph code for the fallback font, and set the font on the current context
if (uniChar != 0)
{
CTFontRef fallback;
if (uniChar > 0xFFFF) {
UTF16Char charRef[2];
JavaCT_BreakupUnicodeIntoSurrogatePairs(uniChar, charRef);
CGGlyph glyphTmp[2];
fallback = JavaCT_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, (const UTF16Char *)&charRef, (CGGlyph *)&glyphTmp, 2);
glyph = glyphTmp[0];
} else {
const UTF16Char u = uniChar;
fallback = JavaCT_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, &u, (CGGlyph *)&glyph, 1);
}
if (fallback) {
const CGFontRef cgFallback = CTFontCopyGraphicsFont(fallback, NULL);
CFRelease(fallback);
if (cgFallback) {
if (!saved) {
CGContextSaveGState(cgRef);
saved = true;
}
CGContextSetFont(cgRef, cgFallback);
CFRelease(cgFallback);
}
}
} else {
if (saved) {
CGContextRestoreGState(cgRef);
saved = false;
}
}
// if we have per-glyph transformations
int tin = (g_gvTXIndicesAsInts == NULL) ? -1 : (g_gvTXIndicesAsInts[i] - 1) * 6;
@@ -214,10 +132,6 @@ void JavaCT_DrawGlyphVector
pt.y += advances[i].height;
}
// reset the font on the context after striking a unicode with CoreText
if (saved) {
CGContextRestoreGState(cgRef);
}
}
// Using the Quartz Surface Data context, draw a hot-substituted character run
@@ -327,24 +241,16 @@ static jclass jc_StandardGlyphVector = NULL;
// Checks the GlyphVector Java object for any transforms that were applied to individual characters. If none are present,
// strike the glyphs immediately in Core Graphics. Otherwise, obtain the arrays, and defer to above.
static inline void doDrawGlyphsPipe_checkForPerGlyphTransforms
(JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector, BOOL useSubstituion, int *uniChars, CGGlyph *glyphs, CGSize *advances, size_t length)
(JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector, CGGlyph *glyphs, CGSize *advances, size_t length)
{
// if we have no character substitution, and no per-glyph transformations - strike now!
// if we have no per-glyph transformations - strike now!
GET_SGV_CLASS();
DECLARE_FIELD(jm_StandardGlyphVector_gti, jc_StandardGlyphVector, "gti", "Lsun/font/StandardGlyphVector$GlyphTransformInfo;");
jobject gti = (*env)->GetObjectField(env, gVector, jm_StandardGlyphVector_gti);
if (gti == 0)
{
if (useSubstituion)
{
// quasi-simple case, substitution, but no per-glyph transforms
JavaCT_DrawGlyphVector(qsdo, strike, TRUE, uniChars, glyphs, advances, NULL, NULL, length);
}
else
{
// fast path, straight to CG without per-glyph transforms
CGContextShowGlyphsWithAdvances(qsdo->cgRef, glyphs, advances, length);
}
// fast path, straight to CG without per-glyph transforms
CGContextShowGlyphsWithAdvances(qsdo->cgRef, glyphs, advances, length);
return;
}
@@ -369,8 +275,8 @@ static inline void doDrawGlyphsPipe_checkForPerGlyphTransforms
(*env)->DeleteLocalRef(env, g_gtiTXIndicesArray);
return;
}
// slowest case, we have per-glyph transforms, and possibly glyph substitution as well
JavaCT_DrawGlyphVector(qsdo, strike, useSubstituion, uniChars, glyphs, advances, g_gvTXIndicesAsInts, g_gvTransformsAsDoubles, length);
// slowest case, we have per-glyph transforms
JavaCT_DrawGlyphVector(qsdo, strike, glyphs, advances, g_gvTXIndicesAsInts, g_gvTransformsAsDoubles, length);
(*env)->ReleasePrimitiveArrayCritical(env, g_gtiTransformsArray, g_gvTransformsAsDoubles, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, g_gtiTXIndicesArray, g_gvTXIndicesAsInts, JNI_ABORT);
@@ -379,35 +285,11 @@ static inline void doDrawGlyphsPipe_checkForPerGlyphTransforms
(*env)->DeleteLocalRef(env, g_gtiTXIndicesArray);
}
// Retrieves advances for translated unicodes
// Uses "glyphs" as a temporary buffer for the glyph-to-unicode translation
void JavaCT_GetAdvancesForUnichars
(const NSFont *font, const int uniChars[], CGGlyph glyphs[], const size_t length, CGSize advances[])
{
// cycle over each spot, and if we discovered a unicode to substitute, we have to calculate the advance for it
size_t i;
for (i = 0; i < length; i++)
{
UniChar uniChar = uniChars[i];
if (uniChar == 0) continue;
CGGlyph glyph = 0;
const CTFontRef fallback = JRSFontCreateFallbackFontForCharacters((CTFontRef)font, &uniChar, 1);
if (fallback) {
CTFontGetGlyphsForCharacters(fallback, &uniChar, &glyph, 1);
CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &(advances[i]), 1);
CFRelease(fallback);
}
glyphs[i] = glyph;
}
}
// Fills the glyph buffer with glyphs from the GlyphVector object. Also checks to see if the glyph's positions have been
// already caculated from GlyphVector, or we simply ask Core Graphics to make some advances for us. Pre-calculated positions
// are translated into advances, since CG only understands advances.
static inline void doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers
(JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector, CGGlyph *glyphs, int *uniChars, CGSize *advances, size_t length, jintArray glyphsArray)
(JNIEnv *env, QuartzSDOps *qsdo, const AWTStrike *strike, jobject gVector, CGGlyph *glyphs, CGSize *advances, size_t length, jintArray glyphsArray)
{
// fill the glyph buffer
jint *glyphsAsInts = (*env)->GetPrimitiveArrayCritical(env, glyphsArray, NULL);
@@ -415,24 +297,10 @@ static inline void doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers
return;
}
// if a glyph code from Java is negative, that means it is really a unicode value
// which we can use in CoreText to strike the character in another font
size_t i;
BOOL complex = NO;
for (i = 0; i < length; i++)
{
jint code = glyphsAsInts[i];
if (code < 0)
{
complex = YES;
uniChars[i] = -code;
glyphs[i] = 0;
}
else
{
uniChars[i] = 0;
glyphs[i] = code;
}
glyphs[i] = glyphsAsInts[i];
}
(*env)->ReleasePrimitiveArrayCritical(env, glyphsArray, glyphsAsInts, JNI_ABORT);
@@ -483,15 +351,10 @@ static inline void doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers
// there were no pre-calculated positions from the glyph buffer on the Java side
AWTFont *awtFont = strike->fAWTFont;
CTFontGetAdvancesForGlyphs((CTFontRef)awtFont->fFont, kCTFontDefaultOrientation, glyphs, advances, length);
if (complex)
{
JavaCT_GetAdvancesForUnichars(awtFont->fFont, uniChars, glyphs, length, advances);
}
}
// continue on to the next stage of the pipe
doDrawGlyphsPipe_checkForPerGlyphTransforms(env, qsdo, strike, gVector, complex, uniChars, glyphs, advances, length);
doDrawGlyphsPipe_checkForPerGlyphTransforms(env, qsdo, strike, gVector, glyphs, advances, length);
}
// Obtains the glyph array to determine the number of glyphs we are dealing with. If we are dealing a large number of glyphs,
@@ -515,18 +378,16 @@ static inline void doDrawGlyphsPipe_getGlyphVectorLengthAndAlloc
{
// if we are small enough, fit everything onto the stack
CGGlyph glyphs[length];
int uniChars[length];
CGSize advances[length];
doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers(env, qsdo, strike, gVector, glyphs, uniChars, advances, length, glyphsArray);
doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers(env, qsdo, strike, gVector, glyphs, advances, length, glyphsArray);
}
else
{
// otherwise, we should malloc and free buffers for this large run
CGGlyph *glyphs = (CGGlyph *)malloc(sizeof(CGGlyph) * length);
int *uniChars = (int *)malloc(sizeof(int) * length);
CGSize *advances = (CGSize *)malloc(sizeof(CGSize) * length);
if (glyphs == NULL || uniChars == NULL || advances == NULL)
if (glyphs == NULL || advances == NULL)
{
(*env)->DeleteLocalRef(env, glyphsArray);
[NSException raise:NSMallocException format:@"%s-%s:%d", __FILE__, __FUNCTION__, __LINE__];
@@ -534,10 +395,6 @@ static inline void doDrawGlyphsPipe_getGlyphVectorLengthAndAlloc
{
free(glyphs);
}
if (uniChars)
{
free(uniChars);
}
if (advances)
{
free(advances);
@@ -545,10 +402,9 @@ static inline void doDrawGlyphsPipe_getGlyphVectorLengthAndAlloc
return;
}
doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers(env, qsdo, strike, gVector, glyphs, uniChars, advances, length, glyphsArray);
doDrawGlyphsPipe_fillGlyphAndAdvanceBuffers(env, qsdo, strike, gVector, glyphs, advances, length, glyphsArray);
free(glyphs);
free(uniChars);
free(advances);
}

View File

@@ -1008,7 +1008,7 @@ static NSObject *sAttributeNamesLOCK = nil;
point.y += size.height;
// Now make it into Cocoa screen coords.
point.y = [[[[self view] window] screen] frame].size.height - point.y;
point.y = [[NSScreen screens][0] frame].size.height - point.y;
return [NSValue valueWithPoint:point];
}
@@ -1385,7 +1385,7 @@ static NSObject *sAttributeNamesLOCK = nil;
"(Ljava/awt/Container;FF)Ljavax/accessibility/Accessible;", nil);
// Make it into java screen coords
point.y = [[[[self view] window] screen] frame].size.height - point.y;
point.y = [[NSScreen screens][0] frame].size.height - point.y;
jobject jparent = fComponent;

View File

@@ -83,10 +83,11 @@ static NSString* uiBoldName = nil;
(uiBoldName != nil && [name isEqualTo:uiBoldName])) {
if (style & java_awt_Font_BOLD) {
nsFont = [NSFont boldSystemFontOfSize:1.0];
nsFallbackBase = [NSFont fontWithName:@"LucidaGrande-Bold" size:1.0];
} else {
nsFont = [NSFont systemFontOfSize:1.0];
nsFallbackBase = [NSFont fontWithName:@"LucidaGrande" size:1.0];
}
nsFallbackBase = [NSFont fontWithName:@"Lucida Grande" size:1.0];
#ifdef DEBUG
NSLog(@"nsFont-name is : %@", nsFont.familyName);
NSLog(@"nsFont-family is : %@", nsFont.fontName);
@@ -3341,6 +3342,64 @@ Java_sun_awt_FontDescriptor_initIDs
}
#endif
/*
* Class: sun_font_CFont
* Method: getCascadeList
* Signature: (JLjava/util/ArrayList;)V
*/
JNIEXPORT void JNICALL
Java_sun_font_CFont_getCascadeList
(JNIEnv *env, jclass cls, jlong awtFontPtr, jobject arrayListOfString)
{
JNI_COCOA_ENTER(env);
jclass alc = (*env)->FindClass(env, "java/util/ArrayList");
if (alc == NULL) return;
jmethodID addMID = (*env)->GetMethodID(env, alc, "add", "(Ljava/lang/Object;)Z");
if (addMID == NULL) return;
CFIndex i;
AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
NSFont* nsFont = awtFont->fFont;
#ifdef DEBUG
CFStringRef base = CTFontCopyFullName((CTFontRef)nsFont);
NSLog(@"BaseFont is : %@", (NSString*)base);
CFRelease(base);
#endif
bool anotherBaseFont = false;
if (awtFont->fFallbackBase != nil) {
nsFont = awtFont->fFallbackBase;
anotherBaseFont = true;
}
CTFontRef font = (CTFontRef)nsFont;
CFArrayRef codes = CFLocaleCopyISOLanguageCodes();
CFArrayRef fds = CTFontCopyDefaultCascadeListForLanguages(font, codes);
CFRelease(codes);
CFIndex cnt = CFArrayGetCount(fds);
for (i= anotherBaseFont ? -1 : 0; i<cnt; i++) {
CFStringRef fontname;
if (i < 0) {
fontname = CTFontCopyPostScriptName(font);
} else {
CTFontDescriptorRef ref = CFArrayGetValueAtIndex(fds, i);
fontname = CTFontDescriptorCopyAttribute(ref, kCTFontNameAttribute);
}
#ifdef DEBUG
NSLog(@"Font is : %@", (NSString*)fontname);
#endif
jstring jFontName = (jstring)NSStringToJavaString(env, fontname);
CFRelease(fontname);
(*env)->CallBooleanMethod(env, arrayListOfString, addMID, jFontName);
if ((*env)->ExceptionOccurred(env)) {
CFRelease(fds);
return;
}
(*env)->DeleteLocalRef(env, jFontName);
}
CFRelease(fds);
JNI_COCOA_EXIT(env);
}
static CFStringRef EMOJI_FONT_NAME = CFSTR("Apple Color Emoji");
bool IsEmojiFont(CTFontRef font)

View File

@@ -28,7 +28,6 @@
#import "sun_font_CStrikeDisposer.h"
#import "CGGlyphImages.h"
#import "CGGlyphOutlines.h"
#import "CoreTextSupport.h"
#import "JNIUtilities.h"
#include "fontscalerdefs.h"
#import "LWCToolkit.h"
@@ -160,12 +159,8 @@ JNI_COCOA_ENTER(env);
AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr);
AWTFont *awtFont = awtStrike->fAWTFont;
// negative glyph codes are really unicodes, which were placed there by the mapper
// to indicate we should use CoreText to substitute the character
CGGlyph glyph;
const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph);
CGGlyphImages_GetGlyphMetrics(fallback, &awtStrike->fAltTx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, NULL, &advance, IS_OSX_GT10_14);
CFRelease(fallback);
CGGlyph glyph = glyphCode;
CGGlyphImages_GetGlyphMetrics((CTFontRef)awtFont->fFont, &awtStrike->fAltTx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, NULL, &advance, IS_OSX_GT10_14);
advance = CGSizeApplyAffineTransform(advance, awtStrike->fFontTx);
if (!JRSFontStyleUsesFractionalMetrics(awtStrike->fStyle)) {
advance.width = round(advance.width);
@@ -195,14 +190,9 @@ JNI_COCOA_ENTER(env);
tx.tx += x;
tx.ty += y;
// negative glyph codes are really unicodes, which were placed there by the mapper
// to indicate we should use CoreText to substitute the character
CGGlyph glyph;
const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph);
CGGlyph glyph = glyphCode;
CGRect bbox;
CGGlyphImages_GetGlyphMetrics(fallback, &tx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, &bbox, NULL, IS_OSX_GT10_14);
CFRelease(fallback);
CGGlyphImages_GetGlyphMetrics((CTFontRef)awtFont->fFont, &tx, awtStrike->fSize, awtStrike->fStyle, &glyph, 1, &bbox, NULL, IS_OSX_GT10_14);
// the origin of this bounding box is relative to the bottom-left corner baseline
CGFloat decender = -bbox.origin.y;
@@ -251,14 +241,12 @@ AWT_FONT_CLEANUP_CHECK(awtfont);
tx.tx += xPos;
tx.ty += yPos;
// get the right font and glyph for this "Java GlyphCode"
CGGlyph glyph;
const CTFontRef font = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtfont, glyphCode, &glyph);
CGGlyph glyph = glyphCode;
NSFont *font = awtfont->fFont;
// get the advance of this glyph
CGSize advance;
CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &glyph, &advance, 1);
CTFontGetAdvancesForGlyphs((CTFontRef)font, kCTFontDefaultOrientation, &glyph, &advance, 1);
// Create AWTPath
path = AWTPathCreate(CGSizeMake(xPos, yPos));
@@ -267,8 +255,7 @@ AWT_FONT_CLEANUP_CHECK(path);
// Get the paths
tx = awtStrike->fTx;
tx = CGAffineTransformConcat(tx, sInverseTX);
AWTGetGlyphOutline(&glyph, (NSFont *)font, &advance, &tx, 0, 1, &path);
CFRelease(font);
AWTGetGlyphOutline(&glyph, font, &advance, &tx, 0, 1, &path);
pointCoords = (*env)->NewFloatArray(env, path->fNumberOfDataElements);
AWT_FONT_CLEANUP_CHECK(pointCoords);
@@ -322,19 +309,14 @@ JNIEXPORT void JNICALL Java_sun_font_CStrike_getNativeGlyphOutlineBounds
AWT_FONT_CLEANUP_SETUP;
AWT_FONT_CLEANUP_CHECK(awtfont);
// get the right font and glyph for this "Java GlyphCode"
CGGlyph glyph;
const CTFontRef font = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(
awtfont, glyphCode, &glyph);
CGGlyph glyph = glyphCode;
CGRect bbox = CTFontGetBoundingRectsForGlyphs(
font, kCTFontOrientationDefault, &glyph, NULL, 1);
(CTFontRef)awtfont->fFont, kCTFontOrientationDefault, &glyph, NULL, 1);
CGAffineTransform tx = CGAffineTransformConcat(awtStrike->fTx,
sInverseTX);
bbox = CGRectApplyAffineTransform (bbox, tx);
CFRelease(font);
jfloat *rawRectData =
(*env)->GetPrimitiveArrayCritical(env, rectData, NULL);

View File

@@ -29,7 +29,6 @@
#import "CoreTextSupport.h"
#import "sun_font_CCharToGlyphMapper.h"
#import "sun_font_CCompositeGlyphMapper.h"
/*
* Class: sun_font_CCharToGlyphMapper
@@ -114,28 +113,3 @@ JNI_COCOA_ENTER(env);
JNI_COCOA_EXIT(env);
}
/*
* Class: sun_font_CCompositeGlyphMapper
* Method: nativeCodePointToGlyph
* Signature: (JI[Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
Java_sun_font_CCompositeGlyphMapper_nativeCodePointToGlyph
(JNIEnv *env, jclass clazz, jlong awtFontPtr, jint codePoint, jobjectArray resultArray)
{
JNI_COCOA_ENTER(env);
AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr);
CFStringRef fontNames[] = {NULL, NULL};
CGGlyph glyph = CTS_CopyGlyphAndFontNamesForCodePoint(awtFont, (UnicodeScalarValue)codePoint, fontNames);
if (glyph > 0) {
jstring fontName = NSStringToJavaString(env, (NSString *)fontNames[0]);
(*env)->SetObjectArrayElement(env, resultArray, 0, fontName);
jstring fontFamilyName = NSStringToJavaString(env, (NSString *)fontNames[1]);
(*env)->SetObjectArrayElement(env, resultArray, 1, fontFamilyName);
}
if (fontNames[0]) CFRelease(fontNames[0]);
if (fontNames[1]) CFRelease(fontNames[1]);
return glyph;
JNI_COCOA_EXIT(env);
}

View File

@@ -27,7 +27,6 @@
#import "JNIUtilities.h"
#import "CGGlyphImages.h"
#import "CoreTextSupport.h"
#import "fontscalerdefs.h" // contains the definition of GlyphInfo struct
#import "sun_awt_SunHints.h"
@@ -739,78 +738,6 @@ CGGI_CreateImageForGlyph
/*
* CoreText path...
*/
static inline GlyphInfo *
CGGI_CreateImageForUnicode
(CGGI_GlyphCanvas *canvas, const AWTStrike *strike,
const CGGI_RenderingMode *mode, const UnicodeScalarValue uniChar,
const bool isCatalinaOrAbove)
{
// save the graphics state
CGContextSaveGState(canvas->context);
// text matrix is not considered part of graphics state
CGAffineTransform originalTx = CGContextGetTextMatrix(canvas->context);
// get the glyph, measure it using CG
CGGlyph glyph;
CTFontRef fallback;
if (uniChar > 0xFFFF) {
UTF16Char charRef[2];
CTS_BreakupUnicodeIntoSurrogatePairs(uniChar, charRef);
CGGlyph glyphTmp[2];
fallback = CTS_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, (const UTF16Char *)&charRef, (CGGlyph *)&glyphTmp, 2);
glyph = glyphTmp[0];
} else {
UTF16Char charRef;
charRef = (UTF16Char) uniChar; // truncate.
fallback = CTS_CopyCTFallbackFontAndGlyphForUnicode(strike->fAWTFont, (const UTF16Char *)&charRef, &glyph, 1);
}
JRSFontRenderingStyle style = JRSFontAlignStyleForFractionalMeasurement(strike->fStyle);
CGGI_GlyphInfoDescriptor *glyphDescriptor = CGGI_GetGlyphInfoDescriptor(mode, fallback);
bool subpixelResolution = mode->subpixelResolution && glyphDescriptor == &grey;
CGRect bbox;
CGSize advance;
CGGlyphImages_GetGlyphMetrics(fallback, &strike->fTx, strike->fSize, style, &glyph, 1, &bbox, &advance, isCatalinaOrAbove);
// create the Sun2D GlyphInfo we are going to strike into
GlyphInfo *info = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, glyphDescriptor, subpixelResolution);
// fix the context size, just in case the substituted character is unexpectedly large
CGGI_SizeCanvas(canvas, info->width * info->subpixelResolutionX, info->height * info->subpixelResolutionY, mode);
// align the transform for the real CoreText strike
CGContextSetTextMatrix(canvas->context, strike->fAltTx);
const CGFontRef cgFallback = CTFontCopyGraphicsFont(fallback, NULL);
CGContextSetFont(canvas->context, cgFallback);
CFRelease(cgFallback);
// clean the canvas - align, strike, and copy the glyph from the canvas into the info
CGGI_CreateImageForGlyph(canvas, glyph, info, glyphDescriptor, strike, fallback, isCatalinaOrAbove);
// restore graphics state
CGContextRestoreGState(canvas->context);
CGContextSetTextMatrix(canvas->context, originalTx);
CFRelease(fallback);
#ifdef CGGI_DEBUG
DUMP_GLYPHINFO(info);
#endif
#ifdef CGGI_DEBUG_DUMP
DUMP_IMG_PIXELS("CGGI Canvas", canvas->image);
#if 0
PRINT_CGSTATES_INFO(NULL);
#endif
#endif
return info;
}
#pragma mark --- GlyphInfo Filling and Canvas Managment ---
@@ -825,7 +752,6 @@ CGGI_FillImagesForGlyphsWithSizedCanvas(CGGI_GlyphCanvas *canvas,
const AWTStrike *strike,
const CGGI_RenderingMode *mode,
jlong glyphInfos[],
const UnicodeScalarValue uniChars[],
const CGGlyph glyphs[],
const CFIndex len)
{
@@ -838,13 +764,8 @@ CGGI_FillImagesForGlyphsWithSizedCanvas(CGGI_GlyphCanvas *canvas,
CFIndex i;
for (i = 0; i < len; i++) {
GlyphInfo *info = (GlyphInfo *)jlong_to_ptr(glyphInfos[i]);
if (info != NULL) {
CGGI_CreateImageForGlyph(canvas, glyphs[i], info, mode->mainFontDescriptor,
strike, (CTFontRef)strike->fAWTFont->fFont, isMojaveOrAbove);
} else {
info = CGGI_CreateImageForUnicode(canvas, strike, mode, uniChars[i], isMojaveOrAbove);
glyphInfos[i] = ptr_to_jlong(info);
}
CGGI_CreateImageForGlyph(canvas, glyphs[i], info, mode->mainFontDescriptor,
strike, (CTFontRef)strike->fAWTFont->fFont, isMojaveOrAbove);
#ifdef CGGI_DEBUG
DUMP_GLYPHINFO(info);
#endif
@@ -879,7 +800,7 @@ static NSString *threadLocalLCDCanvasKey =
static inline void
CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
const CGGI_RenderingMode *mode,
const UnicodeScalarValue uniChars[], const CGGlyph glyphs[],
const CGGlyph glyphs[],
const size_t maxWidth, const size_t maxHeight,
const CFIndex len)
{
@@ -889,8 +810,7 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
CGGI_GlyphCanvas *tmpCanvas = [[CGGI_GlyphCanvas alloc] init];
CGGI_InitCanvas(tmpCanvas, maxWidth, maxHeight, mode);
CGGI_FillImagesForGlyphsWithSizedCanvas(tmpCanvas, strike,
mode, glyphInfos, uniChars,
glyphs, len);
mode, glyphInfos, glyphs, len);
CGGI_FreeCanvas(tmpCanvas);
[tmpCanvas release];
@@ -910,7 +830,7 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
CGGI_SizeCanvas(canvas, maxWidth, maxHeight, mode);
CGGI_FillImagesForGlyphsWithSizedCanvas(canvas, strike, mode,
glyphInfos, uniChars, glyphs, len);
glyphInfos, glyphs, len);
}
/*
@@ -926,7 +846,7 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
static inline void
CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike,
const CGGI_RenderingMode *mode,
const UnicodeScalarValue uniChars[], const CGGlyph glyphs[],
const CGGlyph glyphs[],
CGSize advances[], CGRect bboxes[], const CFIndex len)
{
AWTFont *font = strike->fAWTFont;
@@ -941,12 +861,6 @@ CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike,
CFIndex i;
for (i = 0; i < len; i++)
{
if (uniChars[i] != 0)
{
glyphInfos[i] = 0L;
continue; // will be handled later
}
CGSize advance = advances[i];
CGRect bbox = bboxes[i];
@@ -963,41 +877,29 @@ CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike,
glyphInfos[i] = ptr_to_jlong(glyphInfo);
}
CGGI_FillImagesForGlyphs(glyphInfos, strike, mode, uniChars,
CGGI_FillImagesForGlyphs(glyphInfos, strike, mode,
glyphs, maxWidth, maxHeight, len);
}
#pragma mark --- Temporary Buffer Allocations and Initialization ---
/*
* This stage separates the already valid glyph codes from the unicode values
* that need special handling - the rawGlyphCodes array is no longer used
* after this stage.
*/
static void
CGGI_CreateGlyphsAndScanForComplexities(jlong *glyphInfos,
const AWTStrike *strike,
const CGGI_RenderingMode *mode,
jint rawGlyphCodes[],
UnicodeScalarValue uniChars[], CGGlyph glyphs[],
CGSize advances[], CGRect bboxes[],
const CFIndex len)
CGGI_CreateGlyphs(jlong *glyphInfos,
const AWTStrike *strike,
const CGGI_RenderingMode *mode,
jint rawGlyphCodes[],
CGGlyph glyphs[],
CGSize advances[], CGRect bboxes[],
const CFIndex len)
{
CFIndex i;
for (i = 0; i < len; i++) {
jint code = rawGlyphCodes[i];
if (code < 0) {
glyphs[i] = 0;
uniChars[i] = -code;
} else {
glyphs[i] = code;
uniChars[i] = 0;
}
glyphs[i] = rawGlyphCodes[i];
}
CGGI_CreateGlyphInfos(glyphInfos, strike, mode,
uniChars, glyphs, advances, bboxes, len);
glyphs, advances, bboxes, len);
#ifdef CGGI_DEBUG_HIT_COUNT
static size_t hitCount = 0;
@@ -1023,31 +925,29 @@ CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[],
CGRect bboxes[len];
CGSize advances[len];
CGGlyph glyphs[len];
UnicodeScalarValue uniChars[len];
CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode,
rawGlyphCodes, uniChars, glyphs,
advances, bboxes, len);
CGGI_CreateGlyphs(glyphInfos, strike, &mode,
rawGlyphCodes, glyphs,
advances, bboxes, len);
return;
}
// just do one malloc, and carve it up for all the buffers
void *buffer = malloc(sizeof(CGRect) * sizeof(CGSize) *
sizeof(CGGlyph) * sizeof(UnicodeScalarValue) * len);
void *buffer = malloc((sizeof(CGRect) + sizeof(CGSize) + sizeof(CGGlyph)) *
len);
if (buffer == NULL) {
[[NSException exceptionWithName:NSMallocException
reason:@"Failed to allocate memory for the temporary glyph strike and measurement buffers." userInfo:nil] raise];
}
CGRect *bboxes = (CGRect *)(buffer);
CGSize *advances = (CGSize *)(bboxes + sizeof(CGRect) * len);
CGGlyph *glyphs = (CGGlyph *)(advances + sizeof(CGGlyph) * len);
UnicodeScalarValue *uniChars = (UnicodeScalarValue *)(glyphs + sizeof(UnicodeScalarValue) * len);
CGSize *advances = (CGSize *)(bboxes + len);
CGGlyph *glyphs = (CGGlyph *)(advances + len);
CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode,
rawGlyphCodes, uniChars, glyphs,
advances, bboxes, len);
CGGI_CreateGlyphs(glyphInfos, strike, &mode,
rawGlyphCodes, glyphs,
advances, bboxes, len);
free(buffer);
}

View File

@@ -31,37 +31,13 @@
#pragma mark --- CoreText Support ---
#define HI_SURROGATE_START 0xD800
#define HI_SURROGATE_END 0xDBFF
#define LO_SURROGATE_START 0xDC00
#define LO_SURROGATE_END 0xDFFF
/*
* Transform Unicode characters into glyphs.
*
* Fills the "glyphsAsInts" array with the glyph codes for the current font,
* or the negative unicode value if we know the character can be hot-substituted.
*
* This is the heart of "Universal Font Substitution" in Java.
* Fills the "glyphsAsInts" array with the glyph codes for the current font.
*/
void CTS_GetGlyphsAsIntsForCharacters(const AWTFont *font, const UniChar unicodes[], CGGlyph glyphs[], jint glyphsAsInts[], const size_t count);
// Translates a Java glyph code int (might be a negative unicode value) into a CGGlyph/CTFontRef pair
// Returns the substituted font, and places the appropriate glyph into "glyph"
CTFontRef CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(const AWTFont *font, const jint glyphCode, CGGlyph *glyphRef);
// Translates a Unicode into a CGGlyph/CTFontRef pair
// Returns the substituted font, and places the appropriate glyph into "glyphRef"
CTFontRef CTS_CopyCTFallbackFontAndGlyphForUnicode(const AWTFont *font, const UTF16Char *charRef, CGGlyph *glyphRef, int count);
// Transform a single Unicode character code into glyph code.
// Names of the relevant font are also returned, if the substitution is used.
// Non-null components of fontNames array should always be released by the calling code, regardless of the returned value.
CGGlyph CTS_CopyGlyphAndFontNamesForCodePoint(const AWTFont *font, const UnicodeScalarValue codePoint, CFStringRef fontNames[]);
// Breakup a 32 bit unicode value into the component surrogate pairs
void CTS_BreakupUnicodeIntoSurrogatePairs(int uniChar, UTF16Char charRef[]);
// Basic struct that holds everything CoreText is interested in
typedef struct CTS_ProviderStruct {

View File

@@ -88,161 +88,18 @@ ReleaseCTStateDictionary(CFDictionaryRef ctStateDict)
CFRelease(ctStateDict); // GC
}
void GetFontsAndGlyphsForCharacters(CTFontRef font, CTFontRef fallbackBase,
const UniChar unicodes[], CGGlyph glyphs[], jint glyphsAsInts[],
CTFontRef actualFonts[], const size_t count)
{
CTFontGetGlyphsForCharacters(font, unicodes, glyphs, count);
if (!fallbackBase) fallbackBase = font;
size_t i;
for (i = 0; i < count; i++) {
UniChar unicode = unicodes[i];
UniChar nextUnicode = (i+1) < count ? unicodes[i+1] : 0;
bool surrogatePair = unicode >= HI_SURROGATE_START && unicode <= HI_SURROGATE_END
&& nextUnicode >= LO_SURROGATE_START && nextUnicode <= LO_SURROGATE_END;
CGGlyph glyph = glyphs[i];
if (glyph > 0) {
glyphsAsInts[i] = glyph;
if (surrogatePair) i++;
continue;
}
const CTFontRef fallback = JRSFontCreateFallbackFontForCharacters(fallbackBase, &unicodes[i], surrogatePair ? 2 : 1);
if (fallback) {
CTFontGetGlyphsForCharacters(fallback, &unicodes[i], &glyphs[i], surrogatePair ? 2 : 1);
glyph = glyphs[i];
if (actualFonts && glyph > 0) {
actualFonts[i] = fallback;
} else {
CFRelease(fallback);
}
}
if (glyph > 0) {
int codePoint = surrogatePair ? (((int)(unicode - HI_SURROGATE_START)) << 10)
+ nextUnicode - LO_SURROGATE_START + 0x10000 : unicode;
glyphsAsInts[i] = -codePoint; // set the glyph code to the negative unicode value
} else {
glyphsAsInts[i] = 0; // CoreText couldn't find a glyph for this character either
}
if (surrogatePair) i++;
}
}
/*
* Transform Unicode characters into glyphs.
*
* Fills the "glyphsAsInts" array with the glyph codes for the current font,
* or the negative unicode value if we know the character can be hot-substituted.
*
* This is the heart of "Universal Font Substitution" in Java.
* Fills the "glyphsAsInts" array with the glyph codes for the current font.
*/
void CTS_GetGlyphsAsIntsForCharacters
(const AWTFont *font, const UniChar unicodes[], CGGlyph glyphs[], jint glyphsAsInts[], const size_t count)
{
GetFontsAndGlyphsForCharacters((CTFontRef)font->fFont, (CTFontRef)font->fFallbackBase,
unicodes, glyphs, glyphsAsInts, NULL, count);
}
CTFontGetGlyphsForCharacters((CTFontRef)font->fFont, unicodes, glyphs, count);
/*
* Returns glyph code for a given Unicode character.
* Names of the corresponding substituted font are also returned if substitution is performed.
*/
CGGlyph CTS_CopyGlyphAndFontNamesForCodePoint
(const AWTFont *font, const UnicodeScalarValue codePoint, CFStringRef fontNames[])
{
CTFontRef fontRef = (CTFontRef)font->fFont;
CTFontRef fallbackBase = (CTFontRef)font->fFallbackBase;
int count = codePoint >= 0x10000 ? 2 : 1;
UTF16Char unicodes[count];
if (count == 1) {
unicodes[0] = (UTF16Char)codePoint;
} else {
CTS_BreakupUnicodeIntoSurrogatePairs(codePoint, unicodes);
}
CGGlyph glyphs[count];
jint glyphsAsInts[count];
CTFontRef actualFonts[count];
GetFontsAndGlyphsForCharacters(fontRef, fallbackBase, unicodes, glyphs, glyphsAsInts, actualFonts, count);
CGGlyph glyph = glyphs[0];
bool substitutionHappened = glyphsAsInts[0] < 0;
if (glyph > 0 && substitutionHappened) {
CTFontRef actualFont = actualFonts[0];
CFStringRef fontName = CTFontCopyPostScriptName(actualFont);
CFStringRef familyName = CTFontCopyFamilyName(actualFont);
CFRelease(actualFont);
fontNames[0] = fontName;
fontNames[1] = familyName;
if (!fontName || !familyName) glyph = 0;
}
return glyph;
}
/*
* Translates a Unicode into a CGGlyph/CTFontRef pair
* Returns the substituted font, and places the appropriate glyph into "glyphRef"
*/
CTFontRef CTS_CopyCTFallbackFontAndGlyphForUnicode
(const AWTFont *font, const UTF16Char *charRef, CGGlyph *glyphRef, int count) {
CTFontRef primary = (CTFontRef)font->fFont;
CTFontRef fallbackBase = (CTFontRef)font->fFallbackBase;
if (fallbackBase) {
CTFontGetGlyphsForCharacters(primary, charRef, glyphRef, count);
if (glyphRef[0] > 0) {
CFRetain(primary);
return primary;
}
} else {
fallbackBase = primary;
}
CTFontRef fallback = JRSFontCreateFallbackFontForCharacters(fallbackBase, charRef, count);
if (fallback == NULL)
{
// use the original font if we somehow got duped into trying to fallback something we can't
fallback = (CTFontRef)font->fFont;
CFRetain(fallback);
}
CTFontGetGlyphsForCharacters(fallback, charRef, glyphRef, count);
return fallback;
}
/*
* Translates a Java glyph code int (might be a negative unicode value) into a CGGlyph/CTFontRef pair
* Returns the substituted font, and places the appropriate glyph into "glyphRef"
*/
CTFontRef CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode
(const AWTFont *font, const jint glyphCode, CGGlyph *glyphRef)
{
// negative glyph codes are really unicodes, which were placed there by the mapper
// to indicate we should use CoreText to substitute the character
if (glyphCode >= 0)
{
*glyphRef = glyphCode;
CFRetain(font->fFont);
return (CTFontRef)font->fFont;
}
int codePoint = -glyphCode;
if (codePoint >= 0x10000) {
UTF16Char chars[2];
CGGlyph glyphs[2];
CTS_BreakupUnicodeIntoSurrogatePairs(codePoint, chars);
CTFontRef result = CTS_CopyCTFallbackFontAndGlyphForUnicode(font, chars, glyphs, 2);
*glyphRef = glyphs[0];
return result;
} else {
UTF16Char character = codePoint;
return CTS_CopyCTFallbackFontAndGlyphForUnicode(font, &character, glyphRef, 1);
size_t i;
for (i = 0; i < count; i++) {
glyphsAsInts[i] = glyphs[i];
}
}
// Breakup a 32 bit unicode value into the component surrogate pairs
void CTS_BreakupUnicodeIntoSurrogatePairs(int uniChar, UTF16Char charRef[]) {
int value = uniChar - 0x10000;
UTF16Char low_surrogate = (value & 0x3FF) | LO_SURROGATE_START;
UTF16Char high_surrogate = (((int)(value & 0xFFC00)) >> 10) | HI_SURROGATE_START;
charRef[0] = high_surrogate;
charRef[1] = low_surrogate;
}

View File

@@ -44,7 +44,6 @@ static jint vertexCacheIndex = 0;
static MTLPooledTextureHandle * maskCacheTex = NULL;
static jint maskCacheIndex = 0;
static bool gammaCorrection = NO;
static id<MTLRenderCommandEncoder> encoder = NULL;
#define MTLVC_ADD_VERTEX(TX, TY, DX, DY, DZ) \
@@ -144,9 +143,12 @@ MTLVertexCache_InitMaskCache(MTLContext *mtlc) {
}
// init special fully opaque tile in the upper-right corner of
// the mask cache texture
char tile[MTLVC_MASK_CACHE_TILE_SIZE];
memset(tile, 0xff, MTLVC_MASK_CACHE_TILE_SIZE);
static char tile[MTLVC_MASK_CACHE_TILE_SIZE];
static char* pTile = NULL;
if (!pTile) {
memset(tile, 0xff, MTLVC_MASK_CACHE_TILE_SIZE);
pTile = tile;
}
jint texx = MTLVC_MASK_CACHE_TILE_WIDTH * (MTLVC_MASK_CACHE_WIDTH_IN_TILES - 1);
@@ -183,7 +185,7 @@ MTLVertexCache_EnableMaskCache(MTLContext *mtlc, BMTLSDOps *dstOps)
return;
}
}
MTLVertexCache_CreateSamplingEncoder(mtlc, dstOps, gammaCorrection);
MTLVertexCache_CreateSamplingEncoder(mtlc, dstOps, NO);
}
void
@@ -195,7 +197,6 @@ MTLVertexCache_DisableMaskCache(MTLContext *mtlc)
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_DisableMaskCache");
MTLVertexCache_FlushVertexCache(mtlc);
maskCacheIndex = 0;
gammaCorrection = NO;
free(vertexCache);
vertexCache = NULL;
}
@@ -203,7 +204,6 @@ MTLVertexCache_DisableMaskCache(MTLContext *mtlc)
void
MTLVertexCache_CreateSamplingEncoder(MTLContext *mtlc, BMTLSDOps *dstOps, bool gmc) {
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_CreateSamplingEncoder");
gammaCorrection = gmc;
encoder = [mtlc.encoderManager getTextEncoder:dstOps
isSrcOpaque:NO
gammaCorrection:gmc];

View File

@@ -67,6 +67,7 @@ import sun.font.FontDesignMetrics;
import sun.font.FontLineMetrics;
import sun.font.FontManager;
import sun.font.FontManagerFactory;
import sun.font.FontSubstitution;
import sun.font.FontUtilities;
import sun.font.GlyphLayout;
import sun.font.StandardGlyphVector;
@@ -266,6 +267,11 @@ public class Font implements java.io.Serializable
return font.getFont2D();
}
@Override
public Font2D getFont2DWithSubstitution(Font font) {
return font.getFont2DWithSubstitution();
}
public void setFont2D(Font font, Font2DHandle handle) {
font.font2DHandle = handle;
}
@@ -537,6 +543,11 @@ public class Font implements java.io.Serializable
return font2DHandle.font2D;
}
private Font2D getFont2DWithSubstitution() {
Font2D font2D = getFont2D();
return font2D instanceof FontSubstitution ? ((FontSubstitution) font2D).getCompositeFont2D() : font2D;
}
/**
* Creates a new {@code Font} from the specified name, style and
* point size.
@@ -2223,7 +2234,7 @@ public class Font implements java.io.Serializable
* @since 1.2
*/
public boolean canDisplay(char c){
return getFont2D().canDisplay(c);
return getFont2DWithSubstitution().canDisplay(c);
}
/**
@@ -2244,7 +2255,7 @@ public class Font implements java.io.Serializable
throw new IllegalArgumentException("invalid code point: " +
Integer.toHexString(codePoint));
}
return getFont2D().canDisplay(codePoint);
return getFont2DWithSubstitution().canDisplay(codePoint);
}
/**
@@ -2265,7 +2276,7 @@ public class Font implements java.io.Serializable
* @since 1.2
*/
public int canDisplayUpTo(String str) {
Font2D font2d = getFont2D();
Font2D font2d = getFont2DWithSubstitution();
int len = str.length();
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
@@ -2303,7 +2314,7 @@ public class Font implements java.io.Serializable
* @since 1.2
*/
public int canDisplayUpTo(char[] text, int start, int limit) {
Font2D font2d = getFont2D();
Font2D font2d = getFont2DWithSubstitution();
for (int i = start; i < limit; i++) {
char c = text[i];
if (font2d.canDisplay(c)) {
@@ -2338,7 +2349,7 @@ public class Font implements java.io.Serializable
* @since 1.2
*/
public int canDisplayUpTo(CharacterIterator iter, int start, int limit) {
Font2D font2d = getFont2D();
Font2D font2d = getFont2DWithSubstitution();
char c = iter.setIndex(start);
for (int i = start; i < limit; i++, c = iter.next()) {
if (font2d.canDisplay(c)) {

View File

@@ -38,7 +38,7 @@ import java.awt.Font;
* But its probably OK to include it so long as only composites include
* fallbacks. If physicals do then it would be really confusing ..
*/
public class CompositeFont extends Font2D {
public final class CompositeFont extends Font2D {
private boolean[] deferredInitialisation;
String[] componentFileNames;

View File

@@ -108,7 +108,7 @@ public class CompositeGlyphMapper extends CharToGlyphMapper {
return mapper;
}
protected int convertToGlyph(int unicode) {
private int convertToGlyph(int unicode) {
for (int slot = 0; slot < font.numSlots; slot++) {
if (!hasExcludes || !font.isExcludedChar(slot, unicode)) {

View File

@@ -335,7 +335,7 @@ public abstract class Font2D {
return getStrike(desc, true);
}
FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
private FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
/* Before looking in the map, see if the descriptor matches the
* last strike returned from this Font2D. This should often be a win
* since its common for the same font, in the same size to be

View File

@@ -43,6 +43,7 @@ public abstract class FontAccess {
}
public abstract Font2D getFont2D(Font f);
public abstract Font2D getFont2DWithSubstitution(Font f);
public abstract void setFont2D(Font f, Font2DHandle h);
public abstract void setCreatedFont(Font f);
public abstract boolean isCreatedFont(Font f);

View File

@@ -356,7 +356,7 @@ public final class FontDesignMetrics extends FontMetrics {
private void initMatrixAndMetrics() {
Font2D font2D = FontUtilities.getFont2D(font);
Font2D font2D = FontUtilities.getFont2DWithSubstitution(font);
fontStrike = font2D.getStrike(font, frc);
StrikeMetrics metrics = fontStrike.getFontMetrics();
this.ascent = metrics.getAscent();

View File

@@ -266,12 +266,12 @@ public class FontFamily {
doSetFont(fontAndStyle.font, fontAndStyle.style);
}
if (italic == null && plain instanceof FontWithDerivedItalic) {
italic = ((FontWithDerivedItalic)plain).createItalic();
italic = ((FontWithDerivedItalic)plain).createItalicVariant();
}
if (bolditalic == null) {
Font2D boldItalicPrototype = bold != null ? bold : plain;
if (boldItalicPrototype instanceof FontWithDerivedItalic) {
bolditalic = ((FontWithDerivedItalic)boldItalicPrototype).createItalic();
bolditalic = ((FontWithDerivedItalic)boldItalicPrototype).createItalicVariant();
}
}
fontSequence.clear();

View File

@@ -168,6 +168,10 @@ public final class FontUtilities {
return FontAccess.getFontAccess().getFont2D(font);
}
public static Font2D getFont2DWithSubstitution(Font font) {
return FontAccess.getFontAccess().getFont2DWithSubstitution(font);
}
/**
* Return true if there any characters which would trigger layout.
* This method considers supplementary characters to be simple,

View File

@@ -1,5 +1,5 @@
package sun.font;
interface FontWithDerivedItalic {
Font2D createItalic();
Font2D createItalicVariant();
}

View File

@@ -410,10 +410,7 @@ public final class GlyphLayout {
int lang = -1; // default for now
Font2D font2D = FontUtilities.getFont2D(font);
if (font2D instanceof FontSubstitution) {
font2D = ((FontSubstitution)font2D).getCompositeFont2D();
}
Font2D font2D = FontUtilities.getFont2DWithSubstitution(font);
_textRecord.init(text, offset, lim, min, max);
int start = offset;

View File

@@ -197,8 +197,7 @@ public class StandardGlyphVector extends GlyphVector {
// how do we know its a base glyph
// for now, it is if the natural advance of the glyph is non-zero
Font2D f2d = FontUtilities.getFont2D(font);
FontStrike strike = f2d.getStrike(font, frc);
FontStrike strike = font2D.getStrike(font, frc);
float[] deltas = { trackPt.x, trackPt.y };
for (int j = 0; j < deltas.length; ++j) {
@@ -1106,10 +1105,7 @@ public class StandardGlyphVector extends GlyphVector {
}
private void initFontData() {
font2D = FontUtilities.getFont2D(font);
if (font2D instanceof FontSubstitution) {
font2D = ((FontSubstitution)font2D).getCompositeFont2D();
}
font2D = FontUtilities.getFont2DWithSubstitution(font);
float s = font.getSize2D();
if (font.isTransformed()) {
ftx = font.getTransform();
@@ -1728,12 +1724,7 @@ public class StandardGlyphVector extends GlyphVector {
aa, fm);
// Get the strike via the handle. Shouldn't matter
// if we've invalidated the font but its an extra precaution.
// do we want the CompFont from CFont here ?
Font2D f2d = sgv.font2D;
if (f2d instanceof FontSubstitution) {
f2d = ((FontSubstitution)f2d).getCompositeFont2D();
}
FontStrike strike = f2d.handle.font2D.getStrike(desc); // !!! getStrike(desc, false)
FontStrike strike = sgv.font2D.handle.font2D.getStrike(desc); // !!! getStrike(desc, false)
return new GlyphStrike(sgv, strike, dx, dy);
}

View File

@@ -670,7 +670,7 @@ public final class SunGraphics2D
info.nonInvertibleTx =
(Math.abs(textAt.getDeterminant()) <= Double.MIN_VALUE);
info.font2D = FontUtilities.getFont2D(font);
info.font2D = FontUtilities.getFont2DWithSubstitution(font);
int fmhint = fractionalMetricsHint;
if (fmhint == SunHints.INTVAL_FRACTIONALMETRICS_DEFAULT) {

View File

@@ -698,7 +698,7 @@ public abstract class PathGraphics extends ProxyGraphics2D {
}
Font font = g.getFont();
Font2D font2D = FontUtilities.getFont2D(font);
Font2D font2D = FontUtilities.getFont2DWithSubstitution(font);
if (font2D.handle.font2D != font2D) {
/* suspicious, may be a bad font. lets bail */
return false;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2021, 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
@@ -44,6 +44,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.FileTime;
import java.text.MessageFormat;
import java.util.*;
import java.util.function.Consumer;
@@ -120,14 +121,17 @@ public class Main {
Set<Entry> entries = new LinkedHashSet<>();
// module-info.class entries need to be added/updated.
Map<String,byte[]> moduleInfos = new HashMap<>();
Map<String, ModuleInfoEntry> moduleInfos = new HashMap<>();
// A paths Set for each version, where each Set contains directories
// specified by the "-C" operation.
Map<Integer,Set<String>> pathsMap = new HashMap<>();
// There's also a files array per version
Map<Integer,String[]> filesMap = new HashMap<>();
// base version is the first entry and then follow with the version given
// from the --release option in the command-line order.
// The value of each entry is the files given in the command-line order.
Map<Integer,String[]> filesMap = new LinkedHashMap<>();
// Do we think this is a multi-release jar? Set to true
// if --release option found followed by at least file
@@ -772,15 +776,17 @@ public class Main {
private void expand(File dir, String[] files, Set<String> cpaths, int version)
throws IOException
{
if (files == null)
if (files == null) {
return;
}
for (int i = 0; i < files.length; i++) {
File f;
if (dir == null)
if (dir == null) {
f = new File(files[i]);
else
} else {
f = new File(dir, files[i]);
}
boolean isDir = f.isDirectory();
String name = toEntryName(f.getPath(), cpaths, isDir);
@@ -801,19 +807,24 @@ public class Main {
if (f.isFile()) {
Entry e = new Entry(f, name, false);
if (isModuleInfoEntry(name)) {
moduleInfos.putIfAbsent(name, Files.readAllBytes(f.toPath()));
if (uflag)
Path path = f.toPath();
byte[] fileContent = Files.readAllBytes(path);
ModuleInfoEntry mie = new StreamedModuleInfoEntry(name, fileContent, Files.getLastModifiedTime(path));
moduleInfos.putIfAbsent(name, mie);
if (uflag) {
entryMap.put(name, e);
}
} else if (entries.add(e)) {
if (uflag)
if (uflag) {
entryMap.put(name, e);
}
}
} else if (isDir) {
Entry e = new Entry(f, name, true);
if (entries.add(e)) {
// utilize entryMap for the duplicate dir check even in
// case of cflag == true.
// dir name confilict/duplicate could happen with -C option.
// dir name conflict/duplicate could happen with -C option.
// just remove the last "e" from the "entries" (zos will fail
// with "duplicated" entries), but continue expanding the
// sub tree
@@ -822,7 +833,12 @@ public class Main {
} else {
entryMap.put(name, e);
}
expand(f, f.list(), cpaths, version);
String[] dirFiles = f.list();
// Ensure files list is sorted for reproducible jar content
if (dirFiles != null) {
Arrays.sort(dirFiles);
}
expand(f, dirFiles, cpaths, version);
}
} else {
error(formatMsg("error.nosuch.fileordir", String.valueOf(f)));
@@ -895,7 +911,7 @@ public class Main {
*/
boolean update(InputStream in, OutputStream out,
InputStream newManifest,
Map<String,byte[]> moduleInfos,
Map<String, ModuleInfoEntry> moduleInfos,
JarIndex jarIndex) throws IOException
{
ZipInputStream zis = new ZipInputStream(in);
@@ -944,7 +960,7 @@ public class Main {
return false;
}
} else if (moduleInfos != null && isModuleInfoEntry) {
moduleInfos.putIfAbsent(name, zis.readAllBytes());
moduleInfos.putIfAbsent(name, new StreamedModuleInfoEntry(name, zis.readAllBytes(), e.getLastModifiedTime()));
} else {
boolean isDir = e.isDirectory();
if (!entryMap.containsKey(name)) { // copy the old stuff
@@ -1028,15 +1044,21 @@ public class Main {
zos.closeEntry();
}
private void updateModuleInfo(Map<String,byte[]> moduleInfos, ZipOutputStream zos)
private void updateModuleInfo(Map<String, ModuleInfoEntry> moduleInfos, ZipOutputStream zos)
throws IOException
{
String fmt = uflag ? "out.update.module-info": "out.added.module-info";
for (Map.Entry<String,byte[]> mi : moduleInfos.entrySet()) {
for (Map.Entry<String, ModuleInfoEntry> mi : moduleInfos.entrySet()) {
String name = mi.getKey();
byte[] bytes = mi.getValue();
ModuleInfoEntry mie = mi.getValue();
byte[] bytes = mie.readAllBytes();
ZipEntry e = new ZipEntry(name);
e.setTime(System.currentTimeMillis());
FileTime lastModified = mie.getLastModifiedTime();
if (lastModified != null) {
e.setLastModifiedTime(lastModified);
} else {
e.setLastModifiedTime(FileTime.fromMillis(System.currentTimeMillis()));
}
if (flag0) {
crc32ModuleInfo(e, bytes);
}
@@ -1731,12 +1753,23 @@ public class Main {
/**
* Associates a module descriptor's zip entry name along with its
* bytes and an optional URI. Used when describing modules.
* bytes and an optional URI.
*/
interface ModuleInfoEntry {
String name();
Optional<String> uriString();
InputStream bytes() throws IOException;
String name();
Optional<String> uriString();
InputStream bytes() throws IOException;
/**
* @return Returns the last modified time of the module-info.class.
* Returns null if the last modified time is unknown or cannot be
* determined.
*/
FileTime getLastModifiedTime();
default byte[] readAllBytes() throws IOException {
try (InputStream is = bytes()) {
return is.readAllBytes();
}
}
}
static class ZipFileModuleInfoEntry implements ModuleInfoEntry {
@@ -1750,6 +1783,12 @@ public class Main {
@Override public InputStream bytes() throws IOException {
return zipFile.getInputStream(entry);
}
@Override
public FileTime getLastModifiedTime() {
return entry.getLastModifiedTime();
}
/** Returns an optional containing the effective URI. */
@Override public Optional<String> uriString() {
String uri = (Paths.get(zipFile.getName())).toUri().toString();
@@ -1761,14 +1800,28 @@ public class Main {
static class StreamedModuleInfoEntry implements ModuleInfoEntry {
private final String name;
private final byte[] bytes;
StreamedModuleInfoEntry(String name, byte[] bytes) {
private final FileTime lastModifiedTime;
StreamedModuleInfoEntry(String name, byte[] bytes, FileTime lastModifiedTime) {
this.name = name;
this.bytes = bytes;
this.lastModifiedTime = lastModifiedTime;
}
@Override public String name() { return name; }
@Override public InputStream bytes() throws IOException {
return new ByteArrayInputStream(bytes);
}
@Override
public byte[] readAllBytes() throws IOException {
return bytes;
}
@Override
public FileTime getLastModifiedTime() {
return lastModifiedTime;
}
/** Returns an empty optional. */
@Override public Optional<String> uriString() {
return Optional.empty(); // no URI can be derived
@@ -1820,7 +1873,7 @@ public class Main {
while ((e = zis.getNextEntry()) != null) {
String ename = e.getName();
if (isModuleInfoEntry(ename)) {
infos.add(new StreamedModuleInfoEntry(ename, zis.readAllBytes()));
infos.add(new StreamedModuleInfoEntry(ename, zis.readAllBytes(), e.getLastModifiedTime()));
}
}
}
@@ -2033,14 +2086,14 @@ public class Main {
return (classname.replace('.', '/')) + ".class";
}
private boolean checkModuleInfo(byte[] moduleInfoBytes, Set<String> entries)
private boolean checkModuleInfo(ModuleInfoEntry moduleInfoEntry, Set<String> entries)
throws IOException
{
boolean ok = true;
if (moduleInfoBytes != null) { // no root module-info.class if null
if (moduleInfoEntry != null) { // no root module-info.class if null
try {
// ModuleDescriptor.read() checks open/exported pkgs vs packages
ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(moduleInfoBytes));
ModuleDescriptor md = ModuleDescriptor.read(moduleInfoEntry.bytes());
// A module must have the implementation class of the services it 'provides'.
if (md.provides().stream().map(Provides::providers).flatMap(List::stream)
.filter(p -> !entries.contains(toBinaryName(p)))
@@ -2058,15 +2111,19 @@ public class Main {
/**
* Adds extended modules attributes to the given module-info's. The given
* Map values are updated in-place. Returns false if an error occurs.
* Map values are updated in-place.
*/
private void addExtendedModuleAttributes(Map<String,byte[]> moduleInfos,
private void addExtendedModuleAttributes(Map<String, ModuleInfoEntry> moduleInfos,
Set<String> packages)
throws IOException
{
for (Map.Entry<String,byte[]> e: moduleInfos.entrySet()) {
ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(e.getValue()));
e.setValue(extendedInfoBytes(md, e.getValue(), packages));
for (Map.Entry<String, ModuleInfoEntry> e: moduleInfos.entrySet()) {
ModuleInfoEntry mie = e.getValue();
byte[] bytes = mie.readAllBytes();
ModuleDescriptor md = ModuleDescriptor.read(ByteBuffer.wrap(bytes));
byte[] extended = extendedInfoBytes(md, bytes, packages);
// replace the entry value with the extended bytes
e.setValue(new StreamedModuleInfoEntry(mie.name(), extended, mie.getLastModifiedTime()));
}
}

View File

@@ -326,7 +326,7 @@ public class ModuleDotGraph {
private final String name;
private final Graph<String> graph;
private final Set<ModuleDescriptor> descriptors = new TreeSet<>();
private final TreeSet<ModuleDescriptor> descriptors = new TreeSet<>();
private final List<SubGraph> subgraphs = new ArrayList<>();
private final Attributes attributes;
public DotGraphBuilder(String name,
@@ -406,8 +406,8 @@ public class ModuleDotGraph {
.collect(toSet());
String mn = md.name();
edges.stream().forEach(dn -> {
String attr;
edges.stream().sorted().forEach(dn -> {
String attr = "";
if (dn.equals("java.base")) {
attr = "color=\"" + attributes.requiresMandatedColor() + "\"";
} else {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2021, 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
@@ -767,6 +767,10 @@ public class JmodTask {
void processSection(JmodOutputStream out, Section section, Path path)
throws IOException
{
// Keep a sorted set of files to be processed, so that the jmod
// content is reproducible as Files.walkFileTree order is not defined
SortedMap<String, Path> filesToProcess = new TreeMap<String, Path>();
Files.walkFileTree(path, Set.of(FileVisitOption.FOLLOW_LINKS),
Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
@Override
@@ -782,14 +786,21 @@ public class JmodTask {
if (out.contains(section, name)) {
warning("warn.ignore.duplicate.entry", name, section);
} else {
try (InputStream in = Files.newInputStream(file)) {
out.writeEntry(in, section, name);
}
filesToProcess.put(name, file);
}
}
return FileVisitResult.CONTINUE;
}
});
// Process files in sorted order for deterministic jmod content
for (Map.Entry<String, Path> entry : filesToProcess.entrySet()) {
String name = entry.getKey();
Path file = entry.getValue();
try (InputStream in = Files.newInputStream(file)) {
out.writeEntry(in, section, name);
}
}
}
boolean matches(Path path, List<PathMatcher> matchers) {

View File

@@ -41,10 +41,8 @@
# :hotspot_compiler
compiler/ciReplay/TestSAServer.java 8029528 generic-all
compiler/codecache/jmx/PoolsIndependenceTest.java 8167015 generic-all
compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java 8225370 generic-all
compiler/jvmci/compilerToVM/GetFlagValueTest.java 8204459 generic-all
compiler/tiered/LevelTransitionTest.java 8067651 generic-all
compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java 8190680 generic-all
@@ -85,8 +83,6 @@ gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293 macosx-x64
runtime/cds/appcds/jigsaw/modulepath/ModulePathAndCP_JFR.java 8253437 windows-x64
runtime/cds/DeterministicDump.java 8253495 generic-all
runtime/jni/terminatedThread/TestTerminatedThread.java 8219652 aix-ppc64
runtime/ReservedStack/ReservedStackTest.java 8231031 generic-all
containers/docker/TestJFRWithJMX.java 8256417 linux-5.4.17-2011.5.3.el8uek.x86_64
#############################################################################
@@ -95,12 +91,8 @@ containers/docker/TestJFRWithJMX.java 8256417 linux-5.4.17-2011.5.3.el8uek.x86_6
serviceability/sa/sadebugd/DebugdConnectTest.java 8239062 macosx-x64
serviceability/sa/TestRevPtrsForInvokeDynamic.java 8241235 generic-all
serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorStatIntervalTest.java 8214032 generic-all
serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorStatArrayCorrectnessTest.java 8224150 generic-all
serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java 8225354 windows-all
serviceability/attach/RemovingUnixDomainSocketTest.java 8248162 linux-x64
#############################################################################
# :hotspot_misc
@@ -124,8 +116,6 @@ vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Deadlock/JavaDeadlock001/TestD
vmTestbase/nsk/jdi/ThreadReference/stop/stop001/TestDescription.java 7034630 generic-all
vmTestbase/nsk/jdb/eval/eval001/eval001.java 8221503 generic-all
vmTestbase/metaspace/gc/firstGC_10m/TestDescription.java 8208250 generic-all
vmTestbase/metaspace/gc/firstGC_50m/TestDescription.java 8208250 generic-all
vmTestbase/metaspace/gc/firstGC_99m/TestDescription.java 8208250 generic-all
@@ -142,13 +132,6 @@ vmTestbase/jit/escape/LockCoarsening/LockCoarsening001.java 8148743 generic-all
vmTestbase/jit/escape/LockCoarsening/LockCoarsening002.java 8208259 generic-all
vmTestbase/vm/mlvm/indy/func/jvmti/redefineClassInBootstrap/TestDescription.java 8013267 generic-all
vmTestbase/vm/mlvm/meth/func/java/throwException/Test.java 8058176 generic-all
vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java#id1 8058176 generic-all
vmTestbase/vm/mlvm/meth/stress/compiler/i2c_c2i/Test.java 8058176 generic-all
vmTestbase/vm/mlvm/meth/stress/compiler/sequences/Test.java 8058176 generic-all
vmTestbase/vm/mlvm/meth/stress/gc/callSequencesDuringGC/Test.java 8058176 generic-all
vmTestbase/vm/mlvm/meth/stress/java/sequences/Test.java 8058176 generic-all
vmTestbase/vm/mlvm/meth/stress/jdi/breakpointInCompiledCode/Test.java 8058176 generic-all
vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2none_a/TestDescription.java 8013267 generic-all
vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manyDiff_b/TestDescription.java 8013267 generic-all
vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manySame_b/TestDescription.java 8013267 generic-all

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2019, Google and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -36,10 +36,16 @@ package MyPackage;
public class HeapMonitorStatArrayCorrectnessTest {
private static final int maxCount = 10;
// Do 100000 iterations and expect maxIteration / multiplier samples.
private static final int maxIteration = 100000;
// Do 200000 iterations and expect maxIteration / multiplier samples.
private static final int maxIteration = 200_000;
private static int array[];
// 15% error ensures a sanity test without becoming flaky.
// Flakiness is due to the fact that this test is dependent on the sampling interval, which is a
// statistical geometric variable around the sampling interval. This means that the test could be
// unlucky and not achieve the mean average fast enough for the test case.
private static final int acceptedErrorPercentage = 15;
private static void allocate(int size) {
for (int j = 0; j < maxIteration; j++) {
array = new int[size];
@@ -85,11 +91,7 @@ public class HeapMonitorStatArrayCorrectnessTest {
expected *= 4;
expected /= samplingMultiplier;
// 10% error ensures a sanity test without becoming flaky.
// Flakiness is due to the fact that this test is dependent on the sampling interval, which is a
// statistical geometric variable around the sampling interval. This means that the test could be
// unlucky and not achieve the mean average fast enough for the test case.
if (HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
if (HeapMonitor.statsHaveExpectedNumberSamples((int) expected, acceptedErrorPercentage)) {
break;
}
}

View File

@@ -42,7 +42,7 @@ public class HeapMonitorStatIntervalTest {
HeapMonitor.enableSamplingEvents();
int allocationTotal = 10 * 1024 * 1024;
int allocationIterations = 10;
int allocationIterations = 20;
double actualCount = 0;
for (int i = 0; i < allocationIterations; i++) {
@@ -58,13 +58,13 @@ public class HeapMonitorStatIntervalTest {
double error = Math.abs(actualCount - expectedCount);
double errorPercentage = error / expectedCount * 100;
boolean success = (errorPercentage < 10.0);
boolean success = (errorPercentage < 15.0);
System.out.println("Interval: " + interval + ", throw if failure: " + throwIfFailure
+ " - Expected count: " + expectedCount + ", allocationIterations: " + allocationIterations
+ ", actualCount: " + actualCount + " -> " + success);
if (!success && throwIfFailure) {
throw new RuntimeException("Interval average over 10% for interval " + interval + " -> "
throw new RuntimeException("Interval average over 15% for interval " + interval + " -> "
+ actualCount + ", " + expectedCount);
}
@@ -74,7 +74,7 @@ public class HeapMonitorStatIntervalTest {
private static void testInterval(int interval) {
// Test the interval twice, it can happen that the test is "unlucky" and the interval just goes above
// the 10% mark. So try again to squash flakiness.
// the 15% mark. So try again to squash flakiness.
// Flakiness is due to the fact that this test is dependent on the sampling interval, which is a
// statistical geometric variable around the sampling interval. This means that the test could be
// unlucky and not achieve the mean average fast enough for the test case.

View File

@@ -36,11 +36,15 @@ package MyPackage;
/** This test is checking the object allocation path works with heap sampling. */
public class HeapMonitorStatObjectCorrectnessTest {
// Do 200000 iterations and expect maxIteration / multiplier samples.
private static final int maxIteration = 200000;
// Do 400000 iterations and expect maxIteration / multiplier samples.
private static final int maxIteration = 400_000;
private static BigObject obj;
private native static boolean statsHaveExpectedNumberSamples(int expected, int percentError);
// 15% error ensures a sanity test without becoming flaky.
// Flakiness is due to the fact that this test is dependent on the sampling interval, which is a
// statistical geometric variable around the sampling interval. This means that the test could be
// unlucky and not achieve the mean average fast enough for the test case.
private static final int acceptedErrorPercentage = 15;
private static void allocate() {
emptyStorage();
@@ -83,11 +87,7 @@ public class HeapMonitorStatObjectCorrectnessTest {
double expected = maxIteration;
expected /= samplingMultiplier;
// 10% error ensures a sanity test without becoming flaky.
// Flakiness is due to the fact that this test is dependent on the sampling interval, which is a
// statistical geometric variable around the sampling interval. This means that the test could be
// unlucky and not achieve the mean average fast enough for the test case.
if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, acceptedErrorPercentage)) {
throw new RuntimeException("Statistics should show about " + expected + " samples.");
}
}
@@ -108,11 +108,7 @@ public class HeapMonitorStatObjectCorrectnessTest {
double expected = maxIteration;
// 10% error ensures a sanity test without becoming flaky.
// Flakiness is due to the fact that this test is dependent on the sampling interval, which is a
// statistical geometric variable around the sampling interval. This means that the test could be
// unlucky and not achieve the mean average fast enough for the test case.
if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, acceptedErrorPercentage)) {
throw new RuntimeException("Statistics should show about " + expected + " samples.");
}
}

View File

@@ -144,7 +144,7 @@ java/awt/Frame/ExceptionOnSetExtendedStateTest/ExceptionOnSetExtendedStateTest.j
java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java 8144030 macosx-all,linux-all
java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java 7080150 macosx-all
java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java 8168646 generic-all
java/awt/KeyboardFocusmanager/TypeAhead/TestDialogTypeAhead.java 8198626 macosx-all
java/awt/KeyboardFocusmanager/TypeAhead/SubMenuShowTest/SubMenuShowTest.java 8273520 macosx-all
java/awt/Mixing/AWT_Mixing/HierarchyBoundsListenerMixingTest.java 8049405 macosx-all
java/awt/Mixing/AWT_Mixing/OpaqueOverlappingChoice.java 8048171 generic-all
java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java 8159451 linux-all,windows-all,macosx-all
@@ -182,7 +182,6 @@ java/awt/Mixing/AWT_Mixing/JToggleButtonInGlassPaneOverlapping.java 8158801 wind
java/awt/Mixing/AWT_Mixing/JToggleButtonOverlapping.java 8158801 windows-all
java/awt/Mixing/MixingOnDialog.java 8225777 linux-all
java/awt/Mixing/NonOpaqueInternalFrame.java 7124549 macosx-all
java/awt/Mouse/GetMousePositionTest/GetMousePositionWithOverlay.java 8168388 linux-all
java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowRetaining.java 6829264 generic-all
java/awt/datatransfer/DragImage/MultiResolutionDragImageTest.java 8080982 generic-all
java/awt/datatransfer/SystemFlavorMap/AddFlavorTest.java 8079268 linux-all
@@ -191,13 +190,12 @@ java/awt/Toolkit/RealSync/Test.java 6849383 linux-all
java/awt/LightweightComponent/LightweightEventTest/LightweightEventTest.java 8159252 windows-all
java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java 8203047 macosx-all
java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java 8073636 macosx-all
java/awt/FullScreen/FullScreenInsets/FullScreenInsets.java 7019055 windows-all,linux-all
java/awt/FullScreen/FullScreenInsets/FullScreenInsets.java 7019055,8266245 windows-all,linux-all,macosx-aarch64
java/awt/Focus/8013611/JDK8013611.java 8175366 windows-all,macosx-all
java/awt/Focus/6981400/Test1.java 8029675 windows-all,macosx-all
java/awt/Focus/6981400/Test3.java 8173264 generic-all
java/awt/event/KeyEvent/ExtendedKeyCode/ExtendedKeyCodeTest.java 8169476 windows-all,macosx-all
java/awt/event/KeyEvent/KeyChar/KeyCharTest.java 8169474,8224055 macosx-all,windows-all
java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_3.java 6854300 generic-all
java/awt/event/KeyEvent/ExtendedModifiersTest/ExtendedModifiersTest.java 8129778 generic-all
java/awt/event/KeyEvent/KeyMaskTest/KeyMaskTest.java 8129778 generic-all
java/awt/event/KeyEvent/KeyTyped/CtrlASCII.java 8252713 linux-all
@@ -206,7 +204,6 @@ java/awt/event/MouseEvent/MouseButtonsAndKeyMasksTest/MouseButtonsAndKeyMasksTes
java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.java 8194947 generic-all
java/awt/Frame/FramesGC/FramesGC.java 8079069 macosx-all
java/awt/GridLayout/LayoutExtraGaps/LayoutExtraGaps.java 8000171 windows-all
java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java 8196017 windows-all
java/awt/Scrollbar/ScrollbarMouseWheelTest/ScrollbarMouseWheelTest.java 8196018 windows-all,linux-all
java/awt/TrayIcon/ActionCommand/ActionCommand.java 8150540 windows-all
java/awt/TrayIcon/ActionEventMask/ActionEventMask.java 8150540 windows-all
@@ -221,7 +218,6 @@ java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java 8150540 windows-all
java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java 8150540 windows-all
java/awt/TrayIcon/TrayIconPopup/TrayIconPopupClickTest.java 8150540 windows-all,macosx-all
java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java 8150540 windows-all
java/awt/TrayIcon/PopupMenuLeakTest/PopupMenuLeakTest.java 8196440 linux-all
java/awt/Window/ShapedAndTranslucentWindows/SetShapeAndClick.java 8197936 macosx-all
java/awt/Window/ShapedAndTranslucentWindows/SetShapeDynamicallyAndClick.java 8013450 macosx-all
@@ -236,12 +232,10 @@ java/awt/Window/ShapedAndTranslucentWindows/Translucent.java 8222328 windows-all
java/awt/Window/AlwaysOnTop/AutoTestOnTop.java 6847593 linux-all
java/awt/Window/GrabSequence/GrabSequence.java 6848409 macosx-all,linux-all
java/awt/Window/LocationAtScreenCorner/LocationAtScreenCorner.java 8203371 linux-all
java/awt/font/TextLayout/CombiningPerf.java 8192931 generic-all
java/awt/font/TextLayout/TextLayoutBounds.java 8169188 generic-all
java/awt/FontMetrics/FontCrash.java 8198336 windows-all
java/awt/image/BufferedImage/ICMColorDataTest/ICMColorDataTest.java 8233028 generic-all
java/awt/image/DrawImage/IncorrectAlphaSurface2SW.java 8056077 linux-all
java/awt/image/DrawImage/BlitRotateClippedArea.java 8255724 linux-all
java/awt/image/multiresolution/MultiresolutionIconTest.java 8169187,8252812 macosx-all,windows-all,linux-x64
java/awt/print/Headless/HeadlessPrinterJob.java 8196088 windows-all
sun/awt/datatransfer/SuplementaryCharactersTransferTest.java 8011371 generic-all
@@ -257,14 +251,15 @@ sun/java2d/SunGraphics2D/SimplePrimQuality.java 6992007 generic-all
sun/java2d/SunGraphics2D/SourceClippingBlitTest/SourceClippingBlitTest.java 8196185 generic-all
sun/java2d/X11SurfaceData/SharedMemoryPixmapsTest/SharedMemoryPixmapsTest.sh 8221451 linux-all
java/awt/FullScreen/DisplayChangeVITest/DisplayChangeVITest.java 8169469 windows-all
java/awt/FullScreen/DisplayChangeVITest/DisplayChangeVITest.java 8169469,8273618 windows-all,macosx-aarch64
java/awt/FullScreen/UninitializedDisplayModeChangeTest/UninitializedDisplayModeChangeTest.java 8273617 macosx-all
java/awt/print/PrinterJob/PSQuestionMark.java 7003378 generic-all
java/awt/print/PrinterJob/GlyphPositions.java 7003378 generic-all
java/awt/Choice/ChoiceMouseWheelTest/ChoiceMouseWheelTest.java 7100044 macosx-all,linux-all
java/awt/Component/GetScreenLocTest/GetScreenLocTest.java 4753654 generic-all
java/awt/Component/SetEnabledPerformance/SetEnabledPerformance.java 8165863 macosx-all
java/awt/Clipboard/HTMLTransferTest/HTMLTransferTest.java 8017454 macosx-all
java/awt/Frame/MiscUndecorated/RepaintTest.java 8079267 windows-all,linux-all
java/awt/Frame/MiscUndecorated/RepaintTest.java 8079267,8266244 windows-all,linux-all,macosx-aarch64
java/awt/Robot/ModifierRobotKey/ModifierRobotKeyTest.java 8157173 generic-all
java/awt/Modal/FileDialog/FileDialogAppModal1Test.java 7186009 macosx-all
java/awt/Modal/FileDialog/FileDialogAppModal2Test.java 7186009 macosx-all
@@ -474,12 +469,11 @@ java/awt/font/TextLayout/LigatureCaretTest.java 8266312 generic-all
java/awt/image/VolatileImage/CustomCompositeTest.java 8199002 windows-all,linux-all
java/awt/image/VolatileImage/GradientPaints.java 8199003 linux-all
java/awt/JAWT/JAWT.sh 8197798 windows-all,linux-all
java/awt/Debug/DumpOnKey/DumpOnKey.java 8202667 windows-all
java/awt/Robot/RobotWheelTest/RobotWheelTest.java 8129827 generic-all
java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java 8202926 linux-all
java/awt/datatransfer/ConstructFlavoredObjectTest/ConstructFlavoredObjectTest.java 8202860 linux-all
java/awt/dnd/DisposeFrameOnDragCrash/DisposeFrameOnDragTest.java 8202790 macosx-all,linux-all
java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java 8202882,8255898 linux-all,macosx-all
java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java 8202882 linux-all
java/awt/dnd/MissingDragExitEventTest/MissingDragExitEventTest.java 8030121 macosx-all,linux-all
java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java 8202931 macosx-all,linux-all
java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java 7124275 macosx-all
@@ -499,11 +493,9 @@ java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsDocModalTest.java 816
java/awt/im/memoryleak/InputContextMemoryLeakTest.java 8023814 linux-all
java/awt/Frame/DisposeParentGC/DisposeParentGC.java 8079786 macosx-all
java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java 8169468 macosx-all
java/awt/TextArea/AutoScrollOnSelectAndAppend/AutoScrollOnSelectAndAppend.java 8213120 macosx-all
java/awt/GraphicsDevice/DisplayModes/CycleDMImage.java 7099223 linux-all,windows-all
java/awt/Window/WindowResizing/DoubleClickTitleBarTest.java 8233557 macosx-all
java/awt/Window/WindowOwnedByEmbeddedFrameTest/WindowOwnedByEmbeddedFrameTest.java 8233558 macosx-all
java/awt/keyboard/AllKeyCode/AllKeyCode.java 8242930 macosx-all
java/awt/FullScreen/8013581/bug8013581.java 8169471 macosx-all
java/awt/event/MouseEvent/RobotLWTest/RobotLWTest.java 8233568 macosx-all
@@ -511,7 +503,6 @@ java/awt/event/MouseEvent/MultipleMouseButtonsTest/MultipleMouseButtonsTest.java
java/awt/event/MouseEvent/ClickDuringKeypress/ClickDuringKeypress.java 8233568 macosx-all
java/awt/event/KeyEvent/DeadKey/DeadKeyMacOSXInputText.java 8233568 macosx-all
java/awt/event/KeyEvent/DeadKey/deadKeyMacOSX.java 8233568 macosx-all
com/apple/eawt/DefaultMenuBar/DefaultMenuBarTest.java 8233648 macosx-all
java/awt/Choice/ChoiceKeyEventReaction/ChoiceKeyEventReaction.java 7185258 macosx-all
java/awt/TrayIcon/RightClickWhenBalloonDisplayed/RightClickWhenBalloonDisplayed.java 8238720 windows-all
java/awt/PopupMenu/PopupMenuLocation.java 8238720 windows-all
@@ -529,6 +520,7 @@ java/awt/Graphics2D/DrawString/DrawRotatedStringUsingRotatedFont.java 8266283 ge
java/awt/KeyboardFocusmanager/TypeAhead/ButtonActionKeyTest/ButtonActionKeyTest.java 8257529 windows-x64
java/awt/Window/GetScreenLocation/GetScreenLocationTest.java 8225787 linux-x64
java/awt/Dialog/MakeWindowAlwaysOnTop/MakeWindowAlwaysOnTop.java 8266243 macosx-aarch64
############################################################################
@@ -549,11 +541,11 @@ java/foreign/TestMismatch.java 8249684 macosx-all
# jdk_lang
java/lang/StringCoding/CheckEncodings.sh 7008363 generic-all
java/lang/ProcessHandle/InfoTest.java 8211847 aix-ppc64
java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java 8151492 generic-all
java/lang/invoke/LFCaching/LFGarbageCollectedTest.java 8078602 generic-all
java/lang/invoke/lambda/LambdaFileEncodingSerialization.java 8249079 linux-x64
java/lang/invoke/RicochetTest.java 8251969 generic-all
############################################################################
@@ -663,7 +655,6 @@ sun/security/provider/KeyStore/DKSTest.sh 8180266 windows-
sun/security/pkcs11/KeyStore/SecretKeysBasic.java 8209398 generic-all
security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java 8224768 generic-all
security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java 8263059 generic-all
sun/security/smartcardio/TestChannel.java 8039280 generic-all
sun/security/smartcardio/TestConnect.java 8039280 generic-all
@@ -742,11 +733,8 @@ javax/swing/dnd/8139050/NativeErrorsInTableDnD.java 8202765 macosx-all,linux-al
javax/swing/Popup/TaskbarPositionTest.java 8065097 macosx-all,linux-all
javax/swing/JEditorPane/6917744/bug6917744.java 8213124 macosx-all
javax/swing/JRootPane/4670486/bug4670486.java 8042381 macosx-all
javax/swing/JPopupMenu/4634626/bug4634626.java 8017175 macosx-all
javax/swing/JFileChooser/FileSystemView/SystemIconTest.java 8268280 windows-x64
javax/swing/plaf/basic/BasicHTML/4251579/bug4251579.java 8137101 linux-x64
javax/swing/JComponent/7154030/bug7154030.java 8268284 macosx-x64
javax/swing/JButton/8151303/PressedIconTest.java 8266246 macosx-aarch64
javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java 8273573 macosx-all
sanity/client/SwingSet/src/ToolTipDemoTest.java 8225012 windows-all,macosx-all
sanity/client/SwingSet/src/ScrollPaneDemoTest.java 8225013 linux-all

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2021, 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
@@ -24,18 +24,21 @@
/**
* @test
* @key headful
* @bug 8007267
* @bug 8007267 8233648
* @summary [macosx] com.apple.eawt.Application.setDefaultMenuBar is not working
* @requires (os.family == "mac")
* @author leonid.romanov@oracle.com
* @modules java.desktop/sun.awt
* java.desktop/com.apple.eawt
* @run main DefaultMenuBarTest
* @modules java.desktop/com.apple.eawt
* @run main/othervm DefaultMenuBarTest
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Robot;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.lang.reflect.Method;
@@ -50,14 +53,11 @@ public class DefaultMenuBarTest {
}
System.setProperty("apple.laf.useScreenMenuBar", "true");
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
createAndShowGUI();
}
});
SwingUtilities.invokeAndWait(DefaultMenuBarTest::createAndShowGUI);
Robot robot = new Robot();
robot.setAutoDelay(100);
robot.waitForIdle();
robot.keyPress(KeyEvent.VK_META);
robot.keyPress(ks.getKeyCode());
@@ -76,13 +76,7 @@ public class DefaultMenuBarTest {
JMenuItem newItem = new JMenuItem("Open");
newItem.setAccelerator(ks);
newItem.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e) {
listenerCallCounter++;
}
}
);
newItem.addActionListener(e -> listenerCallCounter++);
menu.add(newItem);
JMenuBar defaultMenu = new JMenuBar();
@@ -104,7 +98,7 @@ public class DefaultMenuBarTest {
}
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2021, 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
@@ -26,68 +26,68 @@
@key headful
@bug 4140484
@summary Heavyweight components inside invisible lightweight containers still show
@author Your Name: art@sparc.spb.su
@run main NativeInLightShow
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Container;
import java.awt.Frame;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.InputEvent;
// The test verifies that the mixing code correctly handles COMPONENT_SHOWN events
// while the top-level container is invisible.
public class NativeInLightShow
{
public class NativeInLightShow {
//Declare things used in the test, like buttons and labels here
static boolean buttonPressed = false;
public static void main(String args[]) throws Exception {
Frame f = new Frame("Test");
static volatile boolean buttonPressed = false;
Robot robot = null;
robot = new Robot();
robot.setAutoDelay(50);
public static void main(String[] args) throws Exception {
Frame frame = new Frame("Test");
Container c = new Container();
c.setLayout(new BorderLayout());
Button b = new Button("I'm should be visible!");
b.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e) {
System.out.println("Test PASSED");
buttonPressed = true;
}
Robot robot = new Robot();
Container container = new Container();
container.setLayout(new BorderLayout());
Button button = new Button("I'm should be visible!");
button.addActionListener(e -> {
System.out.println("Test PASSED");
buttonPressed = true;
});
c.add(b);
f.add(c);
container.add(button);
frame.add(container);
frame.pack();
f.pack();
c.setVisible(false);
c.setVisible(true);
container.setVisible(false);
container.setVisible(true);
// Wait for a while for COMPONENT_SHOW event to be dispatched
robot.waitForIdle();
f.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
robot.waitForIdle();
robot.delay(1000);
Point buttonLocation = b.getLocationOnScreen();
Point buttonLocation = button.getLocationOnScreen();
robot.mouseMove(buttonLocation.x + 5, buttonLocation.y + 5);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
// Wait for a while for ACTION event to be dispatched
robot.waitForIdle();
robot.delay(100);
robot.delay(500);
frame.dispose();
if (!buttonPressed) {
System.out.println("Test FAILED");
throw new RuntimeException("Button was not pressed");
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2021, 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
@@ -22,6 +22,7 @@
*/
import java.awt.AWTException;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Robot;
import java.awt.Window;
@@ -58,9 +59,11 @@ public final class DumpOnKey {
w.setSize(200, 200);
w.setLocationRelativeTo(null);
w.setVisible(true);
w.toFront();
w.requestFocus();
final Robot robot = new Robot();
robot.setAutoDelay(50);
robot.setAutoDelay(100);
robot.setAutoWaitForIdle(true);
robot.mouseMove(w.getX() + w.getWidth() / 2,
w.getY() + w.getHeight() / 2);
@@ -74,7 +77,14 @@ public final class DumpOnKey {
robot.keyRelease(KeyEvent.VK_SHIFT);
robot.keyRelease(KeyEvent.VK_CONTROL);
w.dispose();
try {
EventQueue.invokeAndWait(() -> {
w.dispose();
});
} catch (Exception e) {}
robot.delay(2000);
if (dumped != dump) {
throw new RuntimeException("Exp:" + dump + ", actual:" + dumped);
}

View File

@@ -28,7 +28,7 @@
@summary namefilter is not called for file dialog on windows
@library ../../regtesthelpers
@build Util
@run main FilenameFilterTest
@run main/othervm FilenameFilterTest
*/
import java.awt.*;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2021, 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
@@ -26,7 +26,6 @@
* @bug 6646411
* @summary Tests that full screen window and its children receive resize
event when display mode changes
* @author Dmitri.Trembovetski@sun.com: area=Graphics
* @run main/othervm NoResizeEventOnDMChangeTest
* @run main/othervm -Dsun.java2d.d3d=false NoResizeEventOnDMChangeTest
*/
@@ -151,9 +150,22 @@ public class NoResizeEventOnDMChangeTest {
System.err.printf("----------- Setting DM %dx%d:\n",
dm1.getWidth(), dm1.getHeight());
try {
Frame f = fsWin instanceof Frame ? (Frame) fsWin : (Frame) fsWin.getOwner();
DisplayMode oldMode = f.getGraphicsConfiguration().getDevice().getDisplayMode();
gd.setDisplayMode(dm1);
r1.incDmChanges();
r2.incDmChanges();
sleep(2000);
// Check if setting new display mode actually results in frame being
// placed onto display with different resolution.
DisplayMode newMode = f.getGraphicsConfiguration().getDevice().getDisplayMode();
if (oldMode.getWidth() != newMode.getWidth()
|| oldMode.getHeight() != newMode.getHeight()) {
r1.incDmChanges();
r2.incDmChanges();
} else {
System.out.println("Skipping this iteration. Details:");
System.out.println("Requested device = " + gd);
System.out.println("Actual device = " + f.getGraphicsConfiguration().getDevice());
}
} catch (IllegalArgumentException iae) {}
}
});
@@ -166,6 +178,7 @@ public class NoResizeEventOnDMChangeTest {
fsWin.removeComponentListener(r1);
c.removeComponentListener(r2);
}
try {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
@@ -191,10 +204,14 @@ public class NoResizeEventOnDMChangeTest {
}
static void sleep(long ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException ex) {}
long targetTime = System.currentTimeMillis() + ms;
do {
try {
Thread.sleep(targetTime - System.currentTimeMillis());
} catch (InterruptedException ex) {}
} while (System.currentTimeMillis() < targetTime);
}
static class ResizeEventChecker extends ComponentAdapter {
int dmChanges;
int resizes;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, 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
@@ -26,14 +26,29 @@
@key headful
@bug 4799136
@summary Tests that type-ahead for dialog works and doesn't block program
@library ../../regtesthelpers
@modules java.desktop/sun.awt
@build Util
@run main TestDialogTypeAhead
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.AWTEvent;
import java.awt.Button;
import java.awt.Component;
import java.awt.DefaultKeyboardFocusManager;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.lang.reflect.InvocationTargetException;
public class TestDialogTypeAhead {
@@ -49,8 +64,17 @@ public class TestDialogTypeAhead {
public static void main(final String[] args) {
TestDialogTypeAhead app = new TestDialogTypeAhead();
app.init();
app.start();
try {
app.init();
app.start();
} finally {
if (d != null) {
d.dispose();
}
if (f != null) {
f.dispose();
}
}
}
public void init()
@@ -73,13 +97,12 @@ public class TestDialogTypeAhead {
ok.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
System.err.println("OK pressed");
d.dispose();
f.dispose();
// Typed-ahead key events should only be accepted if
// they arrive after FOCUS_GAINED
if (gotFocus) {
pressSema.raise();
}
}
});
ok.addFocusListener(new FocusAdapter() {
@@ -112,6 +135,7 @@ public class TestDialogTypeAhead {
{
try {
robot = new Robot();
robot.setAutoDelay(100);
} catch (Exception e) {
throw new RuntimeException("Can't create robot:" + e);
}
@@ -128,6 +152,7 @@ public class TestDialogTypeAhead {
robot.keyPress(KeyEvent.VK_SPACE);
robot.keyRelease(KeyEvent.VK_SPACE);
try {
robotSema.doWait(1000);
} catch (InterruptedException ie) {
@@ -149,13 +174,13 @@ public class TestDialogTypeAhead {
if (!pressSema.getState()) {
throw new RuntimeException("Type-ahead doesn't work");
}
}// start()
private void moveMouseOver(Container c) {
private void moveMouseOver(Component c) {
Point p = c.getLocationOnScreen();
Dimension d = c.getSize();
robot.mouseMove(p.x + (int)(d.getWidth()/2), p.y + (int)(d.getHeight()/2));
robot.mouseMove(p.x + (int)(d.getWidth()/2),
p.y + (int)(d.getHeight()/2));
}
private void waitForIdle() {
try {
@@ -209,7 +234,10 @@ public class TestDialogTypeAhead {
}
comp.removeFocusListener(fa);
if (!comp.isFocusOwner()) {
throw new RuntimeException("Can't make " + comp + " focused, current owner is " + KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner());
throw new RuntimeException("Can't make " + comp + " focused,"
+ "current owner is "
+ KeyboardFocusManager
.getCurrentKeyboardFocusManager().getFocusOwner());
}
}
@@ -257,4 +285,3 @@ public class TestDialogTypeAhead {
}
}
}// class TestDialogTypeAhead

View File

@@ -56,6 +56,7 @@ public class ActionEventTest extends Frame {
add(list);
setSize(400,400);
setLayout(new FlowLayout());
setLocationRelativeTo(null);
pack();
setVisible(true);
}
@@ -70,9 +71,9 @@ public class ActionEventTest extends Frame {
if ((md & expectedMask) != expectedMask) {
robot.keyRelease(KeyEvent.VK_ALT);
robot.keyRelease(KeyEvent.VK_SHIFT);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.keyRelease(KeyEvent.VK_SHIFT);
robot.keyRelease(KeyEvent.VK_ALT);
dispose();
throw new RuntimeException("Action Event modifiers are not"
+ " set correctly.");
@@ -87,9 +88,9 @@ public class ActionEventTest extends Frame {
// Press Enter on list item, to generate action event.
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ALT);
robot.keyRelease(KeyEvent.VK_SHIFT);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.keyRelease(KeyEvent.VK_SHIFT);
robot.keyRelease(KeyEvent.VK_ALT);
}
public static void main(String args[]) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2021, 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
@@ -25,6 +25,7 @@ import java.awt.Frame;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Rectangle;
import javax.swing.SwingUtilities;
/*
* @test
@@ -42,23 +43,21 @@ public class GetMousePositionWithOverlay {
public static void main(String[] args) throws Throwable {
robot = new Robot();
robot.setAutoDelay(100);
try{
constructTestUI();
} catch (Exception e) {
try {
SwingUtilities.invokeAndWait(GetMousePositionWithOverlay::constructTestUI);
doTest();
} finally {
dispose();
throw new RuntimeException("Unexpected Exception!");
}
robot.waitForIdle();
doTest();
dispose();
}
private static void doTest() {
frontFrame.toFront();
private static void doTest() throws Exception {
SwingUtilities.invokeAndWait(() -> frontFrame.toFront());
robot.waitForIdle();
Rectangle bounds = new Rectangle(frontFrame.getLocationOnScreen(), frontFrame.getSize());
@@ -67,45 +66,44 @@ public class GetMousePositionWithOverlay {
Point pos = backFrame.getMousePosition();
if (pos != null) {
dispose();
throw new RuntimeException("Test failed. Mouse position should be null but was " + pos);
}
pos = frontFrame.getMousePosition();
if (pos == null) {
dispose();
throw new RuntimeException("Test failed. Mouse position should not be null");
}
robot.mouseMove(189, 189);
robot.mouseMove(bounds.x + bounds.width + 5, bounds.y + bounds.height + 5);
robot.waitForIdle();
pos = backFrame.getMousePosition();
if (pos == null) {
dispose();
throw new RuntimeException("Test failed. Mouse position should not be null");
}
}
private static void dispose() {
private static void dispose() throws Exception {
SwingUtilities.invokeAndWait(() -> {
if (backFrame != null) {
backFrame.dispose();
}
if (backFrame != null) {
backFrame.dispose();
}
if (frontFrame != null) {
frontFrame.dispose();
}
if (frontFrame != null) {
frontFrame.dispose();
}
});
}
private static void constructTestUI() {
backFrame = new Frame();
backFrame.setUndecorated(true);
backFrame.setBounds(100, 100, 100, 100);
backFrame.setResizable(false);
backFrame.setVisible(true);
frontFrame = new Frame();
frontFrame.setUndecorated(true);
frontFrame.setBounds(120, 120, 60, 60);
frontFrame.setResizable(false);
frontFrame.setVisible(true);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2021, 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
@@ -23,8 +23,10 @@
import test.java.awt.regtesthelpers.Util;
import javax.swing.*;
import java.awt.*;
import javax.swing.SwingUtilities;
import java.awt.Frame;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
@@ -33,11 +35,10 @@ import java.awt.event.MouseMotionAdapter;
* @key headful
* @bug 8012026 8027154
* @summary Component.getMousePosition() does not work in an applet on MacOS
* @author Petr Pchelko
* @library ../../regtesthelpers
* @build Util
* @compile GetMousePositionWithPopup.java
* @run main/othervm GetMousePositionWithPopup
* @run main GetMousePositionWithPopup
*/
public class GetMousePositionWithPopup {
@@ -48,6 +49,7 @@ public class GetMousePositionWithPopup {
public static void main(String[] args) throws Exception {
try {
Robot r = Util.createRobot();
r.setAutoDelay(100);
r.mouseMove(0, 0);
Util.waitForIdle(null);
@@ -61,7 +63,7 @@ public class GetMousePositionWithPopup {
Util.waitForIdle(null);
r.mouseMove(149, 149);
Util.waitForIdle(null);
r.mouseMove(150, 150);
r.mouseMove(170, 170);
Util.waitForIdle(null);
} finally {
@@ -78,20 +80,25 @@ public class GetMousePositionWithPopup {
private static void constructTestUI() {
frame1 = new Frame();
frame1.setBounds(100, 100, 100, 100);
frame1.setVisible(true);
frame1.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
if (frame2 != null) {
return;
}
frame2 = new Frame();
frame2.setBounds(120, 120, 120, 120);
frame2.setVisible(true);
frame2.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e)
{
Point positionInFrame2 = frame2.getMousePosition();
if (positionInFrame2.x != 30 || positionInFrame2.y != 30) {
throw new RuntimeException("Wrong position reported. Should be [30, 30] but was [" +
int deltaX = Math.abs(50 - positionInFrame2.x);
int deltaY = Math.abs(50 - positionInFrame2.y);
if (deltaX > 2 || deltaY > 2) {
throw new RuntimeException("Wrong position reported. Should be [50, 50] but was [" +
positionInFrame2.x + ", " + positionInFrame2.y + "]");
}
@@ -101,10 +108,7 @@ public class GetMousePositionWithPopup {
}
}
});
frame2.setVisible(true);
}
});
frame1.setVisible(true);
}
}
}

View File

@@ -101,12 +101,14 @@ public class AutoScrollOnSelectAndAppend {
public AutoScrollOnSelectAndAppend() {
try {
robot = new Robot();
robot.setAutoDelay(100);
} catch (Exception ex) {
throw new RuntimeException("Robot Creation Failed.");
}
frame = new Frame();
frame.setSize(200, 200);
frame.setLayout(new FlowLayout());
frame.setLocationRelativeTo(null);
textArea = new TextArea(5, 20);
composeTextArea();
@@ -128,11 +130,11 @@ public class AutoScrollOnSelectAndAppend {
// Delay to make sure auto scroll is finished.
robot.waitForIdle();
robot.delay(500);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
robot.delay(100);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
robot.waitForIdle();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2021, 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
@@ -54,6 +54,10 @@ public class PopupMenuLeakTest {
static final AtomicReference<WeakReference<PopupMenu>> popupWeakReference = new AtomicReference<>();
static ExtendedRobot robot;
public static void main(String[] args) throws Exception {
if (!SystemTray.isSupported()) {
System.out.println("SystemTray not supported. Skipping the test.");
return;
}
robot = new ExtendedRobot();
SwingUtilities.invokeAndWait(PopupMenuLeakTest::createSystemTrayIcon);
sleep();

View File

@@ -26,7 +26,7 @@
* @bug 8130655
* @summary Tests that window owned by EmbeddedFrame can receive keyboard input
* @requires (os.family == "mac")
* @modules java.desktop/sun.awt
* @modules java.desktop/sun.awt java.desktop/sun.lwawt.macosx:open
* @library ../../regtesthelpers
* @build Util
* @run main WindowOwnedByEmbeddedFrameTest

View File

@@ -90,6 +90,7 @@ public class RecognizedActionTest implements AWTEventListener {
dragGestureListener);
frame.getToolkit().addAWTEventListener(this, AWTEvent.MOUSE_EVENT_MASK);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
Thread.sleep(100);
@@ -165,10 +166,10 @@ public class RecognizedActionTest implements AWTEventListener {
break;
case InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK:
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.waitForIdle();
robot.keyRelease(KeyEvent.VK_SHIFT);
robot.waitForIdle();
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.waitForIdle();
break;
default:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2021, 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
@@ -49,44 +49,70 @@
" move the pointer between B to C.",
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Window;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.InvocationTargetException;
import test.java.awt.regtesthelpers.Util;
import javax.swing.*;
import javax.swing.JButton;
import javax.swing.JFrame;
public class SpuriousExitEnter_3 {
static JFrame frame = new JFrame("SpuriousExitEnter_3_LW");
static JButton jbutton = new JButton("jbutton");
static Frame frame1 = new Frame("SpuriousExitEnter_3_HW");
static Button button1 = new Button("button");
static JFrame frame;
static JButton jbutton;
static EnterExitAdapter frameAdapter;
static EnterExitAdapter buttonAdapter;
static Robot r = Util.createRobot();
static Frame frame1;
static Button button1;
public static void testCase(Window w, Component comp) {
frameAdapter = new EnterExitAdapter(w);
buttonAdapter = new EnterExitAdapter(comp);
static final Robot r = Util.createRobot();
w.addMouseListener(frameAdapter);
comp.addMouseListener(buttonAdapter);
static volatile EnterExitAdapter frameAdapter;
static volatile EnterExitAdapter buttonAdapter;
static volatile Point centerA;
static volatile Point centerB;
static volatile Point centerC_1 ;
static volatile Point centerC_2;
w.setSize(200, 200);
w.add(comp, BorderLayout.NORTH);
w.setLocationRelativeTo(null);
w.setVisible(true);
public static void testCase(Window w, Component comp) throws InterruptedException, InvocationTargetException {
EventQueue.invokeAndWait(()-> {
frameAdapter = new EnterExitAdapter(w);
buttonAdapter = new EnterExitAdapter(comp);
Point centerA = new Point(comp.getLocationOnScreen().x + comp.getWidth() / 2,
comp.getLocationOnScreen().y + comp.getHeight() / 2);
Point centerB = new Point(w.getLocationOnScreen().x + w.getWidth() / 2,
w.getLocationOnScreen().y + w.getHeight() / 2);
//for moving from A outside: don't cross the A area. Move straight to the right.
Point centerC_1 = new Point(w.getLocationOnScreen().x + w.getWidth() + 20, //go right off the border
comp.getLocationOnScreen().y + comp.getHeight() / 2); //don't cross the A area!
w.addMouseListener(frameAdapter);
comp.addMouseListener(buttonAdapter);
w.setSize(200, 200);
w.add(comp, BorderLayout.NORTH);
w.setLocationRelativeTo(null);
w.setVisible(true);
});
r.waitForIdle();
r.delay(1000);
EventQueue.invokeAndWait(()-> {
centerA = new Point(comp.getLocationOnScreen().x + comp.getWidth() / 2,
comp.getLocationOnScreen().y + comp.getHeight() / 2);
centerB = new Point(w.getLocationOnScreen().x + w.getWidth() / 2,
w.getLocationOnScreen().y + w.getHeight() / 2);
//for moving from A outside: don't cross the A area. Move straight to the right.
centerC_1 = new Point(w.getLocationOnScreen().x + w.getWidth() + 20, //go right off the border
comp.getLocationOnScreen().y + comp.getHeight() / 2); //don't cross the A area!
//for moving from B outside: don't cross the B area. Move straight to the bottom.
centerC_2 = new Point(w.getLocationOnScreen().x + w.getWidth() / 2,
w.getLocationOnScreen().y + w.getHeight() + 20); //go below the bottom border
});
//for moving from B outside: don't cross the B area. Move straight to the bottom.
Point centerC_2 = new Point(w.getLocationOnScreen().x + w.getWidth() / 2,
w.getLocationOnScreen().y + w.getHeight() + 20); //go below the bottom border
//A and B areas
Util.pointOnComp(comp, r);
Util.waitForIdle(r);
@@ -118,12 +144,23 @@ public class SpuriousExitEnter_3 {
Util.waitForIdle(r);
}
public static void main(String []s)
{
//LW case:
testCase(frame, jbutton);
//HW case
testCase(frame1, button1);
public static void main(String []s) throws InterruptedException, InvocationTargetException {
EventQueue.invokeAndWait(() -> {
frame = new JFrame("SpuriousExitEnter_3_LW");
jbutton = new JButton("jbutton");
frame1 = new Frame("SpuriousExitEnter_3_HW");
button1 = new Button("button");
});
try {
testCase(frame, jbutton); //LW case
testCase(frame1, button1); //HW case
} finally {
EventQueue.invokeLater(frame::dispose);
EventQueue.invokeLater(frame1::dispose);
}
}
private static void moveBetween(Robot r, Point first, Point second) {
@@ -150,9 +187,9 @@ public class SpuriousExitEnter_3 {
class EnterExitAdapter extends MouseAdapter {
private Component target;
private int enteredEventCount = 0;
private int exitedEventCount = 0;
private final Component target;
private volatile int enteredEventCount = 0;
private volatile int exitedEventCount = 0;
public EnterExitAdapter(Component target) {
this.target = target;
@@ -170,7 +207,7 @@ class EnterExitAdapter extends MouseAdapter {
}
public void zeroCounters(){
System.out.println("Zeroeing on " +target.getClass().getName());
System.out.println("Zeroing on " +target.getClass().getName());
enteredEventCount = 0;
exitedEventCount = 0;
}

View File

@@ -1,85 +0,0 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 6328154 6962082
* @summary ensure that ascii, and latin-1 text without combining marks, both layout faster
* than latin-1 text with combining marks. The presumption is then that the canonical
* GSUB table is being run only on the latter and not on either of the former.
*/
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import static java.awt.Font.*;
public class CombiningPerf {
private static Font font;
private static FontRenderContext frc;
public static void main(String[] args) throws Exception {
System.err.println("start");
GraphicsEnvironment.getLocalGraphicsEnvironment();
font = new Font("Lucida Sans Regular", PLAIN, 12);
frc = new FontRenderContext(null, false, false);
String ascii = "the characters are critical noodles?";
String french = "l'aper\u00e7u caract\u00e8re one \u00e9t\u00e9 cr\u00e9\u00e9s";
String frenchX = "l'aper\u00e7u caracte\u0300re one e\u0301te\u0301 ere\u0301e\u0301s";
// warmup
for (int i = 0; i < 100; ++i) {
TextLayout tl = new TextLayout(french, font, frc);
tl = new TextLayout(ascii, font, frc);
tl = new TextLayout(frenchX, font, frc);
}
/**/
long atime = test(ascii);
System.err.println("atime: " + (atime/1000000.0) + " length: " + ascii.length());
long ftime = test(french);
System.err.println("ftime: " + (ftime/1000000.0) + " length: " + french.length());
long xtime = test(frenchX);
System.err.println("xtime: " + (xtime/1000000.0) + " length: " + frenchX.length());
long limit = xtime * 2 / 3;
if (atime > limit || ftime > limit) {
throw new Exception("took too long");
}
/**/
}
private static long test(String text) {
long start = System.nanoTime();
for (int i = 0; i < 2000; ++i) {
TextLayout tl = new TextLayout(text, font, frc);
}
return System.nanoTime() - start;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2021, 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
@@ -36,7 +36,7 @@ import static java.awt.Transparency.TRANSLUCENT;
/**
* @test
* @bug 8255722
* @bug 8255722 8255724
* @key headful
*/
public class BlitRotateClippedArea {
@@ -103,10 +103,15 @@ public class BlitRotateClippedArea {
throws IOException {
for (int x = 0; x < gold.getWidth(); ++x) {
for (int y = 0; y < gold.getHeight(); ++y) {
if (gold.getRGB(x, y) != img.getRGB(x, y)) {
ImageIO.write(gold, "png", new File("gold.png"));
ImageIO.write(img, "png", new File("snapshot.png"));
throw new RuntimeException("Test failed.");
Color goldColor = new Color(gold.getRGB(x, y));
Color actualColor = new Color(img.getRGB(x, y));
if ((Math.abs(goldColor.getRed() - actualColor.getRed()) > 1) ||
(Math.abs(goldColor.getGreen() - actualColor.getGreen()) > 1) ||
(Math.abs(goldColor.getBlue() - actualColor.getBlue()) > 1)) {
ImageIO.write(gold, "png", new File("gold.png"));
ImageIO.write(img, "png", new File("snapshot.png"));
throw new RuntimeException("Test failed for pixel :"
+ x + "/" + y);
}
}
}

View File

@@ -1,70 +0,0 @@
#
# Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
# @test
# @summary Verify that unsupported encodings are handled gracefully.
# @bug 4629543 4785473
#
# @run shell/timeout=300 CheckEncodings.sh
# set platform-dependent variables
OS=`uname -s`
case "$OS" in
Linux | Darwin | AIX ) ;;
Windows* | CYGWIN* )
echo "Passed"; exit 0 ;;
* ) echo "Unrecognized system!" ; exit 1 ;;
esac
expectPass() {
if [ $1 -eq 0 ]
then echo "--- passed as expected"
else
echo "--- failed"
exit $1
fi
}
runTest() {
echo "Testing:" ${1}
set LC_ALL="${1}"; export LC_ALL
locale
${TESTJAVA}/bin/java ${TESTVMOPTS} -version 2>&1
expectPass $?
}
locale -a > machine_locales.txt
# ${TESTSRC}/locales.txt contains the list of "fully supported" locales
# as defined by the i18n doc for 1.4
cat ${TESTSRC}/locales.txt machine_locales.txt | sort | uniq > locale_union.txt
for i in `xargs < locale_union.txt` ; do
runTest ${i}
done
# random strings
for i in FOO 1234 ZZ; do
runTest ${i}
done

View File

@@ -1,25 +0,0 @@
ar_SA
zh_CN
zh_TW
nl_NL
nl_NL_EURO
en_AU
en_CA
en_GB
en_US
fr_CA
fr_FR
fr_FR_EURO
de_DE
de_DE_EURO
iw_IL
hi_IN
it_IT
it_IT_EURO
ja_JP
ko_KR
pt_BR
es_ES
es_ES_EURO
sv_SE
th_TH

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import org.testng.annotations.Test;
import java.io.IOException;
import java.io.InputStream;
import java.lang.module.ModuleDescriptor;
import java.util.Set;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotSame;
/**
* @test
* @bug 8275509
* @run testng ModuleDescriptorHashCodeTest
* @run testng/othervm -Xshare:off ModuleDescriptorHashCodeTest
* @summary Tests the ModuleDescriptor.hashCode() for boot layer modules
*/
public class ModuleDescriptorHashCodeTest {
/**
* Verifies that the ModuleDescriptor.hashCode() returned by a boot layer module is
* the same as that returned by a ModuleDescriptor constructed from the ModuleDescriptor.Builder
* for the same module.
*/
@Test
public void testBootModuleDescriptor() throws Exception {
Set<Module> bootModules = ModuleLayer.boot().modules();
for (Module bootModule : bootModules) {
System.out.println("Testing module descriptor of boot module " + bootModule);
ModuleDescriptor bootMD = bootModule.getDescriptor();
ModuleDescriptor mdFromBuilder = fromModuleInfoClass(bootModule);
// verify that this object is indeed a different object instance than the boot module descriptor
// to prevent any artificial passing of the test
assertNotSame(mdFromBuilder, bootMD, "ModuleDescriptor loaded from boot layer and " +
"one created from module-info.class unexpectedly returned the same instance");
assertEquals(mdFromBuilder.hashCode(), bootMD.hashCode(),
"Unexpected ModuleDescriptor.hashCode() for " + mdFromBuilder);
assertEquals(mdFromBuilder.compareTo(bootMD), 0,
"Unexpected ModuleDescriptor.compareTo() for " + mdFromBuilder);
}
}
// Returns a ModuleDescriptor parsed out of the module-info.class of the passed Module
private static ModuleDescriptor fromModuleInfoClass(Module module) throws IOException {
try (InputStream moduleInfo = module.getResourceAsStream("module-info.class")) {
if (moduleInfo == null) {
throw new RuntimeException("Could not locate module-info.class in " + module);
}
// internally calls ModuleDescriptor.Builder
return ModuleDescriptor.read(moduleInfo);
}
}
}

View File

@@ -23,18 +23,16 @@
/**
* @test
* @summary Verifies that UNIX socket doesn't throw when opened with
* a non-default file system installed. NB: the opened socket isn't
* supposed to be useable.
* @summary Verifies that an attempt to call SelectorProvider.provider().openSelector()
* on a non-default file system succeeds.
* @library /test/lib
* @build TestProvider UnixSocketInNonDefaultFS
* @run main/othervm -Djava.nio.file.spi.DefaultFileSystemProvider=TestProvider UnixSocketInNonDefaultFS
*/
import java.nio.channels.ServerSocketChannel;
import java.net.StandardProtocolFamily;
import java.nio.channels.spi.SelectorProvider;
public class UnixSocketInNonDefaultFS {
public static void main(String args[]) throws java.io.IOException {
ServerSocketChannel server = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
SelectorProvider.provider().openSelector();
}
}

View File

@@ -0,0 +1,275 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
/*
* @test
* @summary tests the order in which the Properties.store() method writes out the properties
* @bug 8231640
* @run testng PropertiesStoreTest
*/
public class PropertiesStoreTest {
private static final String DATE_FORMAT_PATTERN = "EEE MMM dd HH:mm:ss zzz uuuu";
@DataProvider(name = "propsProvider")
private Object[][] createProps() {
final Properties simple = new Properties();
simple.setProperty("1", "one");
simple.setProperty("2", "two");
simple.setProperty("10", "ten");
simple.setProperty("02", "zero-two");
simple.setProperty("3", "three");
simple.setProperty("0", "zero");
simple.setProperty("00", "zero-zero");
simple.setProperty("0", "zero-again");
final Properties specialChars = new Properties();
// some special chars
simple.setProperty(" 1", "space-one");
simple.setProperty("\t 3 7 \n", "tab-space-three-space-seven-space-newline");
// add some simple chars
simple.setProperty("3", "three");
simple.setProperty("0", "zero");
final Properties overrideCallsSuper = new OverridesEntrySetCallsSuper();
overrideCallsSuper.putAll(simple);
final OverridesEntrySet overridesEntrySet = new OverridesEntrySet();
overridesEntrySet.putAll(simple);
final Properties doesNotOverrideEntrySet = new DoesNotOverrideEntrySet();
doesNotOverrideEntrySet.putAll(simple);
return new Object[][]{
{simple, naturalOrder(simple)},
{specialChars, naturalOrder(specialChars)},
{overrideCallsSuper, naturalOrder(overrideCallsSuper)},
{overridesEntrySet, overridesEntrySet.expectedKeyOrder()},
{doesNotOverrideEntrySet, naturalOrder(doesNotOverrideEntrySet)}
};
}
/**
* Tests that the {@link Properties#store(Writer, String)} API writes out the properties
* in the expected order
*/
@Test(dataProvider = "propsProvider")
public void testStoreWriterKeyOrder(final Properties props, final String[] expectedOrder) throws Exception {
// Properties.store(...) to a temp file
final Path tmpFile = Files.createTempFile("8231640", "props");
try (final Writer writer = Files.newBufferedWriter(tmpFile)) {
props.store(writer, null);
}
testStoreKeyOrder(props, tmpFile, expectedOrder);
}
/**
* Tests that the {@link Properties#store(OutputStream, String)} API writes out the properties
* in the expected order
*/
@Test(dataProvider = "propsProvider")
public void testStoreOutputStreamKeyOrder(final Properties props, final String[] expectedOrder) throws Exception {
// Properties.store(...) to a temp file
final Path tmpFile = Files.createTempFile("8231640", "props");
try (final OutputStream os = Files.newOutputStream(tmpFile)) {
props.store(os, null);
}
testStoreKeyOrder(props, tmpFile, expectedOrder);
}
/**
* {@link Properties#load(InputStream) Loads a Properties instance} from the passed
* {@code Path} and then verifies that:
* - the loaded properties instance "equals" the passed (original) "props" instance
* - the order in which the properties appear in the file represented by the path
* is the same as the passed "expectedOrder"
*/
private void testStoreKeyOrder(final Properties props, final Path storedProps,
final String[] expectedOrder) throws Exception {
// Properties.load(...) from that stored file and verify that the loaded
// Properties has expected content
final Properties loaded = new Properties();
try (final InputStream is = Files.newInputStream(storedProps)) {
loaded.load(is);
}
Assert.assertEquals(loaded, props, "Unexpected properties loaded from stored state");
// now read lines from the stored file and keep track of the order in which the keys were
// found in that file. Compare that order with the expected store order of the keys.
final List<String> actualOrder;
try (final BufferedReader reader = Files.newBufferedReader(storedProps)) {
actualOrder = readInOrder(reader);
}
Assert.assertEquals(actualOrder.size(), expectedOrder.length,
"Unexpected number of keys read from stored properties");
if (!Arrays.equals(actualOrder.toArray(new String[0]), expectedOrder)) {
Assert.fail("Unexpected order of stored property keys. Expected order: " + Arrays.toString(expectedOrder)
+ ", found order: " + actualOrder);
}
}
/**
* Tests that {@link Properties#store(Writer, String)} writes out a proper date comment
*/
@Test
public void testStoreWriterDateComment() throws Exception {
final Properties props = new Properties();
props.setProperty("a", "b");
final Path tmpFile = Files.createTempFile("8231640", "props");
try (final Writer writer = Files.newBufferedWriter(tmpFile)) {
props.store(writer, null);
}
testDateComment(tmpFile);
}
/**
* Tests that {@link Properties#store(OutputStream, String)} writes out a proper date comment
*/
@Test
public void testStoreOutputStreamDateComment() throws Exception {
final Properties props = new Properties();
props.setProperty("a", "b");
final Path tmpFile = Files.createTempFile("8231640", "props");
try (final Writer writer = Files.newBufferedWriter(tmpFile)) {
props.store(writer, null);
}
testDateComment(tmpFile);
}
/**
* Reads each line in the {@code file} and verifies that there is only one comment line
* and that comment line can be parsed into a {@link java.util.Date}
*/
private void testDateComment(Path file) throws Exception {
String comment = null;
try (final BufferedReader reader = Files.newBufferedReader(file)) {
String line = null;
while ((line = reader.readLine()) != null) {
if (line.startsWith("#")) {
if (comment != null) {
Assert.fail("More than one comment line found in the stored properties file " + file);
}
comment = line.substring(1);
}
}
}
if (comment == null) {
Assert.fail("No comment line found in the stored properties file " + file);
}
try {
DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN).parse(comment);
} catch (DateTimeParseException pe) {
Assert.fail("Unexpected date comment: " + comment, pe);
}
}
// returns the property keys in their natural order
private static String[] naturalOrder(final Properties props) {
return new TreeSet<>(props.stringPropertyNames()).toArray(new String[0]);
}
// reads each non-comment line and keeps track of the order in which the property key lines
// were read
private static List<String> readInOrder(final BufferedReader reader) throws IOException {
final List<String> readKeys = new ArrayList<>();
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("#")) {
continue;
}
final String key = line.substring(0, line.indexOf("="));
// the Properties.store(...) APIs write out the keys in a specific format for certain
// special characters. Our test uses some of the keys which have those special characters.
// Here we handle such special character conversion (for only those characters that this test uses).
// replace the backslash character followed by the t character with the tab character
String replacedKey = key.replace("\\t", "\t");
// replace the backslash character followed by the n character with the newline character
replacedKey = replacedKey.replace("\\n", "\n");
// replace backslash character followed by the space character with the space character
replacedKey = replacedKey.replace("\\ ", " ");
readKeys.add(replacedKey);
}
return readKeys;
}
// Extends java.util.Properties and overrides entrySet() to return a reverse
// sorted entries set
private static class OverridesEntrySet extends Properties {
@Override
@SuppressWarnings("unchecked")
public Set<Map.Entry<Object, Object>> entrySet() {
// return a reverse sorted entries set
var entries = super.entrySet();
Comparator<Map.Entry<String, String>> comparator = Map.Entry.comparingByKey(Comparator.reverseOrder());
TreeSet<Map.Entry<String, String>> reverseSorted = new TreeSet<>(comparator);
reverseSorted.addAll((Set) entries);
return (Set) reverseSorted;
}
String[] expectedKeyOrder() {
// returns in reverse order of the property keys' natural ordering
var keys = new ArrayList<>(stringPropertyNames());
keys.sort(Comparator.reverseOrder());
return keys.toArray(new String[0]);
}
}
// Extends java.util.Properties and overrides entrySet() to just return "super.entrySet()"
private static class OverridesEntrySetCallsSuper extends Properties {
@Override
public Set<Map.Entry<Object, Object>> entrySet() {
return super.entrySet();
}
}
// Extends java.util.Properties but doesn't override entrySet() method
private static class DoesNotOverrideEntrySet extends Properties {
@Override
public String toString() {
return "DoesNotOverrideEntrySet - " + super.toString();
}
}
}

View File

@@ -0,0 +1,494 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.TimeZone;
/*
* @test
* @summary Tests that the Properties.store() APIs generate output that is reproducible
* @bug 8231640
* @library /test/lib
* @run driver StoreReproducibilityTest
*/
public class StoreReproducibilityTest {
private static final String DATE_FORMAT_PATTERN = "EEE MMM dd HH:mm:ss zzz uuuu";
private static final String SYS_PROP_JAVA_PROPERTIES_DATE = "java.properties.date";
private static final DateTimeFormatter reproducibleDateTimeFormatter = DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN)
.withLocale(Locale.ROOT).withZone(ZoneOffset.UTC);
public static void main(final String[] args) throws Exception {
// no security manager enabled
testWithoutSecurityManager();
// security manager enabled and security policy explicitly allows
// read permissions on java.properties.date system property
testWithSecMgrExplicitPermission();
// security manager enabled and no explicit permission on java.properties.date system property
testWithSecMgrNoSpecificPermission();
// free form non-date value for java.properties.date system property
testNonDateSysPropValue();
// blank value for java.properties.date system property
testBlankSysPropValue();
// empty value for java.properties.date system property
testEmptySysPropValue();
// value for java.properties.date system property contains line terminator characters
testMultiLineSysPropValue();
// value for java.properties.date system property contains backslash character
testBackSlashInSysPropValue();
}
/**
* Launches a Java program which is responsible for using Properties.store() to write out the
* properties to a file. The launched Java program is passed a value for the
* {@code java.properties.date} system property and the date comment written out
* to the file is expected to use this value.
* The program is launched multiple times with the same value for {@code java.properties.date}
* and the output written by each run of this program is verified to be exactly the same.
* Additionally, the date comment that's written out is verified to be the expected date that
* corresponds to the passed {@code java.properties.date}.
* The launched Java program is run without any security manager
*/
private static void testWithoutSecurityManager() throws Exception {
final List<Path> storedFiles = new ArrayList<>();
final String sysPropVal = reproducibleDateTimeFormatter.format(Instant.ofEpochSecond(243535322));
for (int i = 0; i < 5; i++) {
final Path tmpFile = Files.createTempFile("8231640", ".props");
storedFiles.add(tmpFile);
final ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
"-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=" + sysPropVal,
StoreTest.class.getName(),
tmpFile.toString(),
i % 2 == 0 ? "--use-outputstream" : "--use-writer");
executeJavaProcess(processBuilder);
assertExpectedComment(tmpFile, sysPropVal);
if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
throw new RuntimeException("Unexpected properties stored in " + tmpFile);
}
}
assertAllFileContentsAreSame(storedFiles, sysPropVal);
}
/**
* Launches a Java program which is responsible for using Properties.store() to write out the
* properties to a file. The launched Java program is passed a value for the
* {@code java.properties.date} system property and the date comment written out to the file
* is expected to use this value.
* The launched Java program is run with the default security manager and is granted
* a {@code read} permission on {@code java.properties.date}.
* The program is launched multiple times with the same value for {@code java.properties.date}
* and the output written by each run of this program is verified to be exactly the same.
* Additionally, the date comment that's written out is verified to be the expected date that
* corresponds to the passed {@code java.properties.date}.
*/
private static void testWithSecMgrExplicitPermission() throws Exception {
final Path policyFile = Files.createTempFile("8231640", ".policy");
Files.write(policyFile, Collections.singleton("""
grant {
// test writes/stores to a file, so FilePermission
permission java.io.FilePermission "<<ALL FILES>>", "read,write";
// explicitly grant read permission on java.properties.date system property
// to verify store() APIs work fine
permission java.util.PropertyPermission "java.properties.date", "read";
};
"""));
final List<Path> storedFiles = new ArrayList<>();
final String sysPropVal = reproducibleDateTimeFormatter.format(Instant.ofEpochSecond(1234342423));
for (int i = 0; i < 5; i++) {
final Path tmpFile = Files.createTempFile("8231640", ".props");
storedFiles.add(tmpFile);
final ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
"-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=" + sysPropVal,
"-Djava.security.manager",
"-Djava.security.policy=" + policyFile.toString(),
StoreTest.class.getName(),
tmpFile.toString(),
i % 2 == 0 ? "--use-outputstream" : "--use-writer");
executeJavaProcess(processBuilder);
assertExpectedComment(tmpFile, sysPropVal);
if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
throw new RuntimeException("Unexpected properties stored in " + tmpFile);
}
}
assertAllFileContentsAreSame(storedFiles, sysPropVal);
}
/**
* Launches a Java program which is responsible for using Properties.store() to write out the
* properties to a file. The launched Java program is passed a value for the
* {@code java.properties.date} system property and the date comment written out to the file
* is expected to use this value.
* The launched Java program is run with the default security manager and is NOT granted
* any explicit permission for {@code java.properties.date} system property.
* The program is launched multiple times with the same value for {@code java.properties.date}
* and the output written by each run of this program is verified to be exactly the same.
* Additionally, the date comment that's written out is verified to be the expected date that
* corresponds to the passed {@code java.properties.date}.
*/
private static void testWithSecMgrNoSpecificPermission() throws Exception {
final Path policyFile = Files.createTempFile("8231640", ".policy");
Files.write(policyFile, Collections.singleton("""
grant {
// test writes/stores to a file, so FilePermission
permission java.io.FilePermission "<<ALL FILES>>", "read,write";
// no other grants, not even "read" java.properties.date system property.
// test should still work fine and the date comment should correspond to the value of
// java.properties.date system property.
};
"""));
final List<Path> storedFiles = new ArrayList<>();
final String sysPropVal = reproducibleDateTimeFormatter.format(Instant.ofEpochSecond(1234342423));
for (int i = 0; i < 5; i++) {
final Path tmpFile = Files.createTempFile("8231640", ".props");
storedFiles.add(tmpFile);
final ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
"-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=" + sysPropVal,
"-Djava.security.manager",
"-Djava.security.policy=" + policyFile.toString(),
StoreTest.class.getName(),
tmpFile.toString(),
i % 2 == 0 ? "--use-outputstream" : "--use-writer");
executeJavaProcess(processBuilder);
assertExpectedComment(tmpFile, sysPropVal);
if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
throw new RuntimeException("Unexpected properties stored in " + tmpFile);
}
}
assertAllFileContentsAreSame(storedFiles, sysPropVal);
}
/**
* Launches a Java program which is responsible for using Properties.store() to write out the
* properties to a file. The launched Java program is passed a {@link String#isBlank() blank} value
* for the {@code java.properties.date} system property.
* It is expected and verified in this test that such a value for the system property
* will cause a comment line to be written out with only whitespaces.
* The launched program is expected to complete without any errors.
*/
private static void testBlankSysPropValue() throws Exception {
final List<Path> storedFiles = new ArrayList<>();
final String sysPropVal = " \t";
for (int i = 0; i < 2; i++) {
final Path tmpFile = Files.createTempFile("8231640", ".props");
storedFiles.add(tmpFile);
final ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
"-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=" + sysPropVal,
StoreTest.class.getName(),
tmpFile.toString(),
i % 2 == 0 ? "--use-outputstream" : "--use-writer");
executeJavaProcess(processBuilder);
if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
throw new RuntimeException("Unexpected properties stored in " + tmpFile);
}
String blankCommentLine = findNthComment(tmpFile, 2);
if (blankCommentLine == null) {
throw new RuntimeException("Comment line representing the value of "
+ SYS_PROP_JAVA_PROPERTIES_DATE + " system property is missing in file " + tmpFile);
}
if (!blankCommentLine.isBlank()) {
throw new RuntimeException("Expected comment line to be blank but was " + blankCommentLine);
}
}
assertAllFileContentsAreSame(storedFiles, sysPropVal);
}
/**
* Launches a Java program which is responsible for using Properties.store() to write out the
* properties to a file. The launched Java program is passed a {@link String#isEmpty() empty} value
* for the {@code java.properties.date} system property.
* It is expected and verified in this test that such a value for the system property
* will cause the current date and time to be written out as a comment.
* The launched program is expected to complete without any errors.
*/
private static void testEmptySysPropValue() throws Exception {
for (int i = 0; i < 2; i++) {
final Path tmpFile = Files.createTempFile("8231640", ".props");
final ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
"-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=" + "",
StoreTest.class.getName(),
tmpFile.toString(),
i % 2 == 0 ? "--use-outputstream" : "--use-writer");
Date launchedAt = new Date();
// wait for a second before launching so that we can then expect
// the date written out by the store() APIs to be "after" this launch date
Thread.sleep(1000);
executeJavaProcess(processBuilder);
if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
throw new RuntimeException("Unexpected properties stored in " + tmpFile);
}
assertCurrentDate(tmpFile, launchedAt);
}
}
/**
* Launches a Java program which is responsible for using Properties.store() to write out the
* properties to a file. The launched Java program is passed the {@code java.properties.date}
* system property with a value that doesn't represent a formatted date.
* It is expected and verified in this test that such a value for the system property
* will cause the comment to use that value verbatim. The launched program is expected to complete
* without any errors.
*/
private static void testNonDateSysPropValue() throws Exception {
final String sysPropVal = "foo-bar";
final List<Path> storedFiles = new ArrayList<>();
for (int i = 0; i < 2; i++) {
final Path tmpFile = Files.createTempFile("8231640", ".props");
storedFiles.add(tmpFile);
final ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
"-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=" + sysPropVal,
StoreTest.class.getName(),
tmpFile.toString(),
i % 2 == 0 ? "--use-outputstream" : "--use-writer");
executeJavaProcess(processBuilder);
if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
throw new RuntimeException("Unexpected properties stored in " + tmpFile);
}
assertExpectedComment(tmpFile, sysPropVal);
}
assertAllFileContentsAreSame(storedFiles, sysPropVal);
}
/**
* Launches a Java program which is responsible for using Properties.store() to write out the
* properties to a file. The launched Java program is passed the {@code java.properties.date}
* system property with a value that has line terminator characters.
* It is expected and verified in this test that such a value for the system property
* will cause the comment written out to be multiple separate comments. The launched program is expected
* to complete without any errors.
*/
private static void testMultiLineSysPropValue() throws Exception {
final String[] sysPropVals = {"hello-world\nc=d", "hello-world\rc=d", "hello-world\r\nc=d"};
for (final String sysPropVal : sysPropVals) {
final List<Path> storedFiles = new ArrayList<>();
for (int i = 0; i < 2; i++) {
final Path tmpFile = Files.createTempFile("8231640", ".props");
storedFiles.add(tmpFile);
final ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
"-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=" + sysPropVal,
StoreTest.class.getName(),
tmpFile.toString(),
i % 2 == 0 ? "--use-outputstream" : "--use-writer");
executeJavaProcess(processBuilder);
if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
throw new RuntimeException("Unexpected properties stored in " + tmpFile);
}
// verify this results in 2 separate comment lines in the stored file
String commentLine1 = findNthComment(tmpFile, 2);
String commentLine2 = findNthComment(tmpFile, 3);
if (commentLine1 == null || commentLine2 == null) {
throw new RuntimeException("Did not find the expected multi-line comments in " + tmpFile);
}
if (!commentLine1.equals("hello-world")) {
throw new RuntimeException("Unexpected comment line " + commentLine1 + " in " + tmpFile);
}
if (!commentLine2.equals("c=d")) {
throw new RuntimeException("Unexpected comment line " + commentLine2 + " in " + tmpFile);
}
}
assertAllFileContentsAreSame(storedFiles, sysPropVal);
}
}
/**
* Launches a Java program which is responsible for using Properties.store() to write out the
* properties to a file. The launched Java program is passed the {@code java.properties.date}
* system property with a value that has backslash character.
* It is expected and verified in this test that such a value for the system property
* will not cause any malformed comments or introduce any new properties in the stored content.
* The launched program is expected to complete without any errors.
*/
private static void testBackSlashInSysPropValue() throws Exception {
final String[] sysPropVals = {"\\hello-world", "hello-world\\", "hello-world\\c=d",
"newline-plus-backslash\\\nc=d"};
for (final String sysPropVal : sysPropVals) {
final List<Path> storedFiles = new ArrayList<>();
for (int i = 0; i < 2; i++) {
final Path tmpFile = Files.createTempFile("8231640", ".props");
storedFiles.add(tmpFile);
final ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(
"-D" + SYS_PROP_JAVA_PROPERTIES_DATE + "=" + sysPropVal,
StoreTest.class.getName(),
tmpFile.toString(),
i % 2 == 0 ? "--use-outputstream" : "--use-writer");
executeJavaProcess(processBuilder);
if (!StoreTest.propsToStore.equals(loadProperties(tmpFile))) {
throw new RuntimeException("Unexpected properties stored in " + tmpFile);
}
String commentLine1 = findNthComment(tmpFile, 2);
if (commentLine1 == null) {
throw new RuntimeException("Did not find the expected comment line in " + tmpFile);
}
if (sysPropVal.contains("newline-plus-backslash")) {
if (!commentLine1.equals("newline-plus-backslash\\")) {
throw new RuntimeException("Unexpected comment line " + commentLine1 + " in " + tmpFile);
}
// we expect this specific system property value to be written out into 2 separate comment lines
String commentLine2 = findNthComment(tmpFile, 3);
if (commentLine2 == null) {
throw new RuntimeException(sysPropVal + " was expected to be split into 2 comment line, " +
"but wasn't, in " + tmpFile);
}
if (!commentLine2.equals("c=d")) {
throw new RuntimeException("Unexpected comment line " + commentLine2 + " in " + tmpFile);
}
} else {
if (!commentLine1.equals(sysPropVal)) {
throw new RuntimeException("Unexpected comment line " + commentLine1 + " in " + tmpFile);
}
}
}
assertAllFileContentsAreSame(storedFiles, sysPropVal);
}
}
// launches the java process and waits for it to exit. throws an exception if exit value is non-zero
private static void executeJavaProcess(ProcessBuilder pb) throws Exception {
final OutputAnalyzer outputAnalyzer = ProcessTools.executeProcess(pb);
try {
outputAnalyzer.shouldHaveExitValue(0);
} finally {
// print out any stdout/err that was generated in the launched program
outputAnalyzer.reportDiagnosticSummary();
}
}
// Properties.load() from the passed file and return the loaded Properties instance
private static Properties loadProperties(final Path file) throws IOException {
final Properties props = new Properties();
props.load(Files.newBufferedReader(file));
return props;
}
/**
* Verifies that the comment in the {@code destFile} is same as {@code expectedComment},
* instead of the default date comment.
*/
private static void assertExpectedComment(final Path destFile,
final String expectedComment) throws Exception {
final String actualComment = findNthComment(destFile, 2);
if (actualComment == null) {
throw new RuntimeException("Comment \"" + expectedComment + "\" not found in stored properties " + destFile);
}
if (!expectedComment.equals(actualComment)) {
throw new RuntimeException("Expected comment \"" + expectedComment + "\" but found \"" + actualComment + "\" " +
"in stored properties " + destFile);
}
}
/**
* Verifies that the date comment in the {@code destFile} can be parsed using the
* "EEE MMM dd HH:mm:ss zzz uuuu" format and the time represented by it is {@link Date#after(Date) after}
* the passed {@code date}
*/
private static void assertCurrentDate(final Path destFile, final Date date) throws Exception {
final String dateComment = findNthComment(destFile, 2);
if (dateComment == null) {
throw new RuntimeException("Date comment not found in stored properties " + destFile);
}
System.out.println("Found date comment " + dateComment + " in file " + destFile);
final Date parsedDate;
try {
Instant instant = Instant.from(DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN).parse(dateComment));
parsedDate = new Date(instant.toEpochMilli());
} catch (DateTimeParseException pe) {
throw new RuntimeException("Unexpected date " + dateComment + " in stored properties " + destFile);
}
if (!parsedDate.after(date)) {
throw new RuntimeException("Expected date comment " + dateComment + " to be after " + date
+ " but was " + parsedDate);
}
}
// returns the "Nth" comment from the file. Comment index starts from 1.
private static String findNthComment(Path file, int commentIndex) throws IOException {
List<String> comments = new ArrayList<>();
try (final BufferedReader reader = Files.newBufferedReader(file)) {
String line = null;
while ((line = reader.readLine()) != null) {
if (line.startsWith("#")) {
comments.add(line.substring(1));
if (comments.size() == commentIndex) {
return comments.get(commentIndex - 1);
}
}
}
}
return null;
}
// verifies the byte equality of the contents in each of the files
private static void assertAllFileContentsAreSame(final List<Path> files,
final String sysPropVal) throws Exception {
final byte[] file1Contents = Files.readAllBytes(files.get(0));
for (int i = 1; i < files.size(); i++) {
final byte[] otherFileContents = Files.readAllBytes(files.get(i));
if (!Arrays.equals(file1Contents, otherFileContents)) {
throw new RuntimeException("Properties.store() did not generate reproducible content when " +
SYS_PROP_JAVA_PROPERTIES_DATE + " was set to " + sysPropVal);
}
}
}
static class StoreTest {
private static final Properties propsToStore = new Properties();
static {
propsToStore.setProperty("a", "b");
}
/**
* Uses Properties.store() APIs to store the properties into file
*/
public static void main(final String[] args) throws Exception {
final Path destFile = Path.of(args[0]);
final String comment = "some user specified comment";
System.out.println("Current default timezone is " + TimeZone.getDefault());
if (args[1].equals("--use-outputstream")) {
try (var os = Files.newOutputStream(destFile)) {
propsToStore.store(os, comment);
}
} else {
try (var br = Files.newBufferedWriter(destFile)) {
propsToStore.store(br, comment);
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More