Compare commits

...

14 Commits

Author SHA1 Message Date
Vitaly Provodin
3b2a8d960c update exclude list on results of 21.0.7_b1020.35 test runs 2025-05-26 09:16:28 +04:00
Vitaly Provodin
fc10c4afd6 Revert "JBR-7700 Classes from package java.io. use java.nio.file inside"
This reverts commit a0c48294d2.
2025-05-24 04:33:21 +04:00
Vitaly Provodin
f495b20d38 JBR-8401 exclude Vulkan specific tests from the runs against Legacy Binary builds 2025-05-24 04:33:21 +04:00
Vitaly Provodin
2b49cced4d JBR-8317 exclude vulkan package from _lb builds & calculate GLIBC expected version in checking dependencies 2025-05-24 04:33:21 +04:00
Nikita Tsarev
602205d82c fixup! JBR-8833: Refactor Wayland data device abstraction [WLToolkit] 2025-05-24 04:33:08 +04:00
Sergey Shelomentsev
121248ac6c fixup! JBR-4154 use -V to sort versions 2025-05-24 04:33:07 +04:00
Nikita Tsarev
b74ae9d4f8 JBR-8833: Refactor Wayland data device abstraction [WLToolkit] 2025-05-24 04:33:07 +04:00
Vitaly Provodin
63b62e6c71 fixup! JBR-4154 fix extracting version info from sources 2025-05-24 04:33:07 +04:00
Vitaly Provodin
64e939dcb0 fixup! clean up fixed issues from exclude lists 2025-05-24 04:33:06 +04:00
Vitaly Provodin
1234d9bd13 clean up fixed issues from exclude lists 2025-05-24 04:33:06 +04:00
Vitaly Provodin
74975b9801 fixup! update exclude list on results of 21.0.7_b992.24 test runs 2025-05-24 04:33:05 +04:00
Vitaly Provodin
fd0b79e0f4 JBR-8589 disable CDS specifically for Linux-x86 2025-05-24 04:33:05 +04:00
Vitaly Provodin
a1f2023d76 JBR-8589 replace system CDS with an actual one for IntelliJ 2025-05-24 04:33:04 +04:00
Vitaly Provodin
b367f8f249 update exclude list on results of 21.0.7_b992.24 test runs 2025-05-24 04:33:04 +04:00
83 changed files with 8822 additions and 6336 deletions

View File

@@ -40,8 +40,6 @@ architecture=${3:-x64} # aarch64 or x64
check_bundle_type_maketest
tag_prefix="jbr-"
OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | grep "$tag_prefix" | cut -d "(" -f2 | cut -d ")" -f1 | awk '{print $2}' | sort -t "-" -k 2 -g | tail -n 1 | tr -d ",")
VERSION_FEATURE=$(getVersionProp "DEFAULT_VERSION_FEATURE")
VERSION_INTERIM=$(getVersionProp "DEFAULT_VERSION_INTERIM")
VERSION_UPDATE=$(getVersionProp "DEFAULT_VERSION_UPDATE")
@@ -49,8 +47,15 @@ VERSION_PATCH=$(getVersionProp "DEFAULT_VERSION_PATCH")
[[ $VERSION_UPDATE = 0 ]] && JBSDK_VERSION="$VERSION_FEATURE" || JBSDK_VERSION="${VERSION_FEATURE}.${VERSION_INTERIM}.${VERSION_UPDATE}"
[[ $VERSION_PATCH = 0 ]] || JBSDK_VERSION="${VERSION_FEATURE}.${VERSION_INTERIM}.${VERSION_UPDATE}.${VERSION_PATCH}"
echo "##teamcity[setParameter name='env.JBSDK_VERSION' value='${JBSDK_VERSION}']"
JDK_BUILD_NUMBER=${JDK_BUILD_NUMBER:=$(echo $OPENJDK_TAG | awk -F "-|[+]" '{print $3}')}
tag_prefix="jbr-"
OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | grep "${tag_prefix}${JBSDK_VERSION}" | cut -d "(" -f2 | cut -d ")" -f1 | awk '{print $2}' | sort -t "-" -k 2 -V -f | tail -n 1 | tr -d ",")
JDK_BUILD_NUMBER=$(echo $OPENJDK_TAG | awk -F "-|[+]" '{print $3}')
[ -z $JDK_BUILD_NUMBER ] && JDK_BUILD_NUMBER=1
re='^[0-9]+$'
if ! [[ $JDK_BUILD_NUMBER =~ $re ]] ; then
echo "error: JDK_BUILD_NUMBER Not a number: $JDK_BUILD_NUMBER"
JDK_BUILD_NUMBER=1
fi
echo "##teamcity[setParameter name='env.JDK_UPDATE_NUMBER' value='${JDK_BUILD_NUMBER}']"
VENDOR_NAME="JetBrains s.r.o."
@@ -104,6 +109,12 @@ else
WITH_BUNDLED_FREETYPE=""
fi
if [ "$bundle_type" == "lb" ]; then
WITH_VULKAN=""
else
WITH_VULKAN="--with-vulkan"
fi
REPRODUCIBLE_BUILD_OPTS="--with-source-date=$SOURCE_DATE_EPOCH
--with-hotspot-build-time=$BUILD_TIME
--with-copyright-year=$COPYRIGHT_YEAR

View File

@@ -35,7 +35,7 @@ function do_configure {
--with-version-opt=b"$build_number" \
--with-boot-jdk="$BOOT_JDK" \
--enable-cds=yes \
--with-vulkan \
$WITH_VULKAN \
$DISABLE_WARNINGS_AS_ERRORS \
$STATIC_CONF_ARGS \
$REPRODUCIBLE_BUILD_OPTS \
@@ -113,6 +113,11 @@ case "$bundle_type" in
jbr_name_postfix="_${bundle_type}"
do_maketest=1
;;
"lb")
do_reset_changes=1
jbr_name_postfix="_${bundle_type}"
do_maketest=1
;;
"nomod" | "")
bundle_type=""
;;
@@ -141,7 +146,7 @@ JBRSDK_BUNDLE=jbrsdk
echo Fixing permissions
chmod -R a+r $JSDK
if [ "$bundle_type" == "jcef" ]; then
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "lb" ]; then
git apply -p0 < jb/project/tools/patches/add_jcef_module_aarch64.patch || do_exit $?
update_jsdk_mods $JSDK $JCEF_PATH/jmods $JSDK/jmods $JSDK_MODS_DIR || do_exit $?
cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed
@@ -154,7 +159,7 @@ create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" ||
# create sdk image bundle
modules=$(cat $JSDK/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\n//g) || do_exit $?
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "lb" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then
modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods)
fi
create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $?

View File

@@ -42,7 +42,7 @@ function do_configure {
--with-version-opt=b"$build_number" \
--with-boot-jdk="$BOOT_JDK" \
--enable-cds=yes \
--with-vulkan \
$WITH_VULKAN \
$LINUX_TARGET \
$DISABLE_WARNINGS_AS_ERRORS \
$STATIC_CONF_ARGS \
@@ -121,6 +121,11 @@ case "$bundle_type" in
jbr_name_postfix="_${bundle_type}"
do_maketest=1
;;
"lb")
do_reset_changes=1
jbr_name_postfix="_${bundle_type}"
do_maketest=1
;;
"nomod" | "")
bundle_type=""
;;
@@ -149,7 +154,7 @@ JBRSDK_BUNDLE=jbrsdk
echo Fixing permissions
chmod -R a+r $JSDK
if [ "$bundle_type" == "jcef" ]; then
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "lb" ]; then
git apply -p0 < jb/project/tools/patches/add_jcef_module.patch || do_exit $?
update_jsdk_mods $JSDK $JCEF_PATH/jmods $JSDK/jmods $JSDK_MODS_DIR || do_exit $?
cp $JCEF_PATH/jmods/* $JSDK_MODS_DIR # $JSDK/jmods is not changed
@@ -162,7 +167,7 @@ create_image_bundle "jbr${jbr_name_postfix}" "jbr" $JSDK_MODS_DIR "$modules" ||
# create sdk image bundle
modules=$(cat $JSDK/release | grep MODULES | sed s/MODULES=//g | sed s/' '/','/g | sed s/\"//g | sed s/\\n//g) || do_exit $?
if [ "$bundle_type" == "jcef" ]|| [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "lb" ] || [ "$bundle_type" == "$JBRSDK_BUNDLE" ]; then
modules=${modules},$(get_mods_list "$JCEF_PATH"/jmods)
fi
create_image_bundle "$JBRSDK_BUNDLE${jbr_name_postfix}" $JBRSDK_BUNDLE $JSDK_MODS_DIR "$modules" || do_exit $?

View File

@@ -12,6 +12,7 @@ set -x
#
source jb/project/tools/common/scripts/common.sh
ENABLE_CDS="no"
function do_configure {
linux32 bash configure \
@@ -24,7 +25,7 @@ function do_configure {
--with-version-opt=b"$build_number" \
--with-boot-jdk="$BOOT_JDK" \
$STATIC_CONF_ARGS \
--enable-cds=yes \
--enable-cds=$ENABLE_CDS \
$DISABLE_WARNINGS_AS_ERRORS \
$REPRODUCIBLE_BUILD_OPTS \
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
@@ -51,7 +52,7 @@ function create_image_bundle {
__cds_opt=''
if is_musl; then libc_type_suffix='musl-' ; fi
__cds_opt="--generate-cds-archive"
[ "${ENABLE_CDS}" == "yes" ] && __cds_opt="--generate-cds-archive"
[ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-"
JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}x86-${fastdebug_infix}b${build_number}
@@ -92,7 +93,7 @@ WITH_DEBUG_LEVEL="--with-debug-level=release"
RELEASE_NAME=linux-x86-server-release
case "$bundle_type" in
"jcef")
"jcef" | "lb")
echo "not implemented" && do_exit 1
;;
"nomod" | "")
@@ -119,7 +120,7 @@ JBRSDK_BUNDLE=jbrsdk
echo Fixing permissions
chmod -R a+r $JSDK
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ]; then
if [ "$bundle_type" == "jcef" ] || [ "$bundle_type" == "fd" ] || [ "$bundle_type" == "lb" ]; then
jbr_name_postfix="_${bundle_type}"
else
jbr_name_postfix=""

View File

@@ -68,7 +68,7 @@ $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXECUTABLE_SUFFIX) $(CLASSLIST
$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@.raw \
-Duser.language=en -Duser.country=US \
-cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
build.tools.classlist.HelloClasslist $(LOG_DEBUG)
build.tools.classlist.HelloClasslist jdk/src/classes/build/tools/classlist/clear.classlist $(LOG_DEBUG)
$(GREP) -v HelloClasslist $@.raw > $@.interim
$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -Xshare:dump \
-XX:SharedClassListFile=$@.interim -XX:SharedArchiveFile=$@.jsa \
@@ -79,7 +79,7 @@ $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXECUTABLE_SUFFIX) $(CLASSLIST
-Duser.language=en -Duser.country=US \
--module-path $(SUPPORT_OUTPUTDIR)/classlist.jar \
-cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
build.tools.classlist.HelloClasslist \
build.tools.classlist.HelloClasslist jdk/src/classes/build/tools/classlist/clear.classlist \
2> $(LINK_OPT_DIR)/stderr > $(JLI_TRACE_FILE) \
|| ( \
exitcode=$$? ; \

View File

@@ -36,6 +36,8 @@ import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.net.InetAddress;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
@@ -153,6 +155,20 @@ public class HelloClasslist {
// an inconsistency in the classlist between builds (see JDK-8295951).
// To avoid the problem, load the class explicitly.
Class<?> striped64Class = Class.forName("java.util.concurrent.atomic.Striped64$Cell");
Files.lines(Path.of(args[0])).forEach(line -> {
if (line.isEmpty() || line.charAt(0) == '#') {
return;
}
try {
int index = line.indexOf(' ');
if (index <= 0) {
return;
}
String className = line.substring(0, index).replace('/', '.');
Class.forName(className);
} catch (Exception e) {
}
});
}
public HelloClasslist() {}

File diff suppressed because it is too large Load Diff

View File

@@ -404,7 +404,6 @@ bool SharedClassPathEntry::validate(bool is_class_path) const {
// filters out any archived module classes that do not have a matching runtime
// module path location.
log_warning(cds)("Required classpath entry does not exist: %s", name);
ok = false;
} else if (is_dir()) {
if (!os::dir_is_empty(name)) {
log_warning(cds)("directory is not empty: %s", name);
@@ -844,6 +843,20 @@ bool FileMapInfo::validate_boot_class_paths() {
num = rp_len;
}
mismatch = check_paths(1, num, rp_array, 0, 0);
if (mismatch) {
// To facilitate app deployment, we allow the JAR files to be moved *together* to
// a different location, as long as they are still stored under the same directory
// structure. E.g., the following is OK.
// Extends JDK-8279366 to boot classpath.
unsigned int dumptime_prefix_len = header()->common_app_classpath_prefix_size();
unsigned int runtime_prefix_len = longest_common_app_classpath_prefix_len(num, rp_array);
if (dumptime_prefix_len != 0 || runtime_prefix_len != 0) {
log_info(cds, path)("LCP length for boot classpath (dumptime: %u, runtime: %u)",
dumptime_prefix_len, runtime_prefix_len);
mismatch = check_paths(1, num, rp_array,
dumptime_prefix_len, runtime_prefix_len);
}
}
} else {
// create_path_array() ignores non-existing paths. Although the dump time and runtime boot classpath lengths
// are the same initially, after the call to create_path_array(), the runtime boot classpath length could become

View File

@@ -93,7 +93,9 @@ class SATBMarkQueueSet: public PtrQueueSet {
size_t _buffer_enqueue_threshold;
// SATB is only active during marking. Enqueuing is only done when active.
bool _all_active;
DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, 4 * sizeof(size_t));
#if ! (defined(_WIN64) && DEFAULT_CACHE_LINE_SIZE == 32)
DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, 4 * sizeof(size_t));
#endif
BufferNode* get_completed_buffer();
void abandon_completed_buffers();

View File

@@ -369,18 +369,6 @@ void ConstantPool::remove_unshareable_info() {
// we always set _on_stack to true to avoid having to change _flags during runtime.
_flags |= (_on_stack | _is_shared);
if (!_pool_holder->is_linked() && !_pool_holder->verified_at_dump_time()) {
return;
}
// Resolved references are not in the shared archive.
// Save the length for restoration. It is not necessarily the same length
// as reference_map.length() if invokedynamic is saved. It is needed when
// re-creating the resolved reference array if archived heap data cannot be map
// at runtime.
set_resolved_reference_length(
resolved_references() != nullptr ? resolved_references()->length() : 0);
set_resolved_references(OopHandle());
bool archived = false;
for (int index = 1; index < length(); index++) { // Index 0 is unused
switch (tag_at(index).value()) {
@@ -403,6 +391,19 @@ void ConstantPool::remove_unshareable_info() {
}
}
if (!_pool_holder->is_linked() && !_pool_holder->verified_at_dump_time()) {
return;
}
// Resolved references are not in the shared archive.
// Save the length for restoration. It is not necessarily the same length
// as reference_map.length() if invokedynamic is saved. It is needed when
// re-creating the resolved reference array if archived heap data cannot be map
// at runtime.
set_resolved_reference_length(
resolved_references() != nullptr ? resolved_references()->length() : 0);
set_resolved_references(OopHandle());
if (cache() != nullptr) {
// cache() is null if this class is not yet linked.
cache()->remove_unshareable_info();

View File

@@ -1,163 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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.jetbrains.internal;
import jdk.internal.misc.VM;
import sun.nio.ch.FileChannelImpl;
import sun.security.action.GetPropertyAction;
import java.io.Closeable;
import java.lang.Boolean;
import java.nio.file.FileSystems;
/**
* Internal methods to control the feature of using {@link java.nio.file} inside {@link java.io}.
*/
public class IoOverNio {
/** Preferences of debug logging. */
public static final Debug DEBUG;
public static final boolean IS_ENABLED_IN_GENERAL =
GetPropertyAction.privilegedGetProperty("jbr.java.io.use.nio", "true").equalsIgnoreCase("true");
private static final ThreadLocal<Integer> ALLOW_IN_THIS_THREAD = new ThreadLocal<>();
static {
String value = GetPropertyAction.privilegedGetProperty("jbr.java.io.use.nio.debug", "");
switch (value) {
case "error":
DEBUG = Debug.ERROR;
break;
case "no_error":
DEBUG = Debug.NO_ERROR;
break;
case "all":
DEBUG = Debug.ALL;
break;
default:
DEBUG = Debug.NO;
break;
}
}
private IoOverNio() {
}
public static boolean isAllowedInThisThread() {
return ALLOW_IN_THIS_THREAD.get() == null;
}
/**
* This method helps to prevent infinite recursion in specific areas like class loading.
* An attempt to access {@link FileSystems#getDefault()} during class loading
* would require loading the class of the default file system provider,
* which would recursively require the access to {@link FileSystems#getDefault()}.
* <p>
* Usage:
* <pre>
* {@code
* @SuppressWarnings("try")
* void method() {
* try (var ignored = IoOverNio.disableInThisThread()) {
* // do something here.
* }
* }
* }
* </pre>
* </p>
*
* <hr/>
*
* An implementation note.
* There may be a temptation to call {@link FileSystems#getDefault()} at some very early stage of loading JVM.
* However, it won't be enough.
* {@link FileSystems#getDefault()} forces an immediate load only of
* the corresponding instance of {@link java.nio.file.spi.FileSystemProvider}.
* Meanwhile, a correct operation of a NIO filesystem requires also implementations of {@link java.nio.file.Path},
* {@link java.nio.file.FileSystem}, {@link java.nio.file.attribute.BasicFileAttributes} and many other classes.
* Without this method, the classloader still can dive into an infinite recursion.
*/
public static ThreadLocalCloseable disableInThisThread() {
Integer value = ALLOW_IN_THIS_THREAD.get();
if (value == null) {
value = 0;
}
++value;
ALLOW_IN_THIS_THREAD.set(value);
return ThreadLocalCloseable.INSTANCE;
}
public enum Debug {
NO(false, false),
ERROR(true, false),
NO_ERROR(false, true),
ALL(true, true);
private final boolean writeErrors;
private final boolean writeTraces;
Debug(boolean writeErrors, boolean writeTraces) {
this.writeErrors = writeErrors;
this.writeTraces = writeTraces;
}
private boolean mayWriteAnything() {
return VM.isBooted() && isAllowedInThisThread();
}
public boolean writeErrors() {
return writeErrors && mayWriteAnything();
}
public boolean writeTraces() {
return writeTraces && mayWriteAnything();
}
}
public static class ThreadLocalCloseable implements AutoCloseable {
private static final ThreadLocalCloseable INSTANCE = new ThreadLocalCloseable();
private ThreadLocalCloseable() {
}
@Override
public void close() {
Integer value = ALLOW_IN_THIS_THREAD.get();
--value;
if (value == 0) {
value = null;
}
ALLOW_IN_THIS_THREAD.set(value);
}
}
/**
* Since it's complicated to change Java API, some new function arguments are transferred via thread local variables.
* This variable allows to set {@code parent} in {@link FileChannelImpl} and therefore to avoid closing the file
* descriptor too early.
* <p>
* The problem was found with the test {@code jtreg:test/jdk/java/io/FileDescriptor/Sharing.java}.
*/
public static final ThreadLocal<Closeable> PARENT_FOR_FILE_CHANNEL_IMPL = new ThreadLocal<>();
}

View File

@@ -1,61 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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.jetbrains.internal;
import java.io.IOException;
import java.util.WeakHashMap;
/**
* The only purpose of this class is to mimic exception messages of `java.io`
* when `java.nio.file` is used as a backend.
*/
public class IoToNioErrorMessageHolder {
private IoToNioErrorMessageHolder() { }
/**
* While an exception is being thrown and handled inside {@code catch}-blocks,
* at least one strong reference exists in the stack.
* GC won't bring harm if {@link #removeMessage(IOException)} is called inside a {@code catch}-block.
*/
private static final WeakHashMap<IOException, String> messages = new WeakHashMap<>();
public static void addMessage(IOException e, String message) {
if (IoOverNio.IS_ENABLED_IN_GENERAL) {
synchronized (messages) {
messages.put(e, message);
}
}
}
public static String removeMessage(IOException e) {
if (IoOverNio.IS_ENABLED_IN_GENERAL) {
synchronized (messages) {
return messages.remove(e);
}
}
return null;
}
}

View File

@@ -1,70 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 java.io;
import sun.nio.ch.FileChannelImpl;
import java.nio.channels.FileChannel;
/**
* A channel returned by {@link #getInterruptibleChannel()} must be interruptible,
* but the channel used inside this class must be uninterruptible.
* This class holds the channel for external usage, which may differ from {@link #channel}.
*/
class ExternalChannelHolder {
private final Object synchronizationPoint;
private final FileChannel channel;
private final NioChannelCleanable channelCleanable;
private FileChannel externallySharedChannel;
ExternalChannelHolder(Object owner, FileChannel channel, NioChannelCleanable channelCleanable) {
this.synchronizationPoint = owner;
this.channel = channel;
this.channelCleanable = channelCleanable;
}
FileChannel getInterruptibleChannel() {
synchronized (synchronizationPoint) {
if (externallySharedChannel == null) {
externallySharedChannel = channel;
if (externallySharedChannel instanceof FileChannelImpl fci) {
fci = fci.clone();
fci.setInterruptible();
externallySharedChannel = fci;
}
}
}
channelCleanable.setChannel(null);
return externallySharedChannel;
}
void close() throws IOException {
FileChannel ch = externallySharedChannel;
if (ch != null) {
ch.close();
}
}
}

View File

@@ -35,11 +35,7 @@ import java.nio.file.Path;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import com.jetbrains.internal.IoOverNio;
import jdk.internal.util.StaticProperty;
import sun.security.action.GetPropertyAction;
/**
* An abstract representation of file and directory pathnames.
@@ -152,18 +148,11 @@ import sun.security.action.GetPropertyAction;
public class File
implements Serializable, Comparable<File>
{
/**
* The FileSystem object representing the platform's local file system.
*/
private static final FileSystem FS;
static {
if (IoOverNio.IS_ENABLED_IN_GENERAL) {
FS = new IoOverNioFileSystem(DefaultFileSystem.getFileSystem());
} else {
FS = DefaultFileSystem.getFileSystem();
}
}
private static final FileSystem FS = DefaultFileSystem.getFileSystem();
/**
* This abstract pathname's normalized pathname string. A normalized

View File

@@ -25,25 +25,12 @@
package java.io;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.Set;
import com.jetbrains.internal.IoOverNio;
import jdk.internal.misc.Blocker;
import jdk.internal.util.ArraysSupport;
import jdk.internal.vm.annotation.Stable;
import sun.nio.ch.FileChannelImpl;
import static com.jetbrains.internal.IoOverNio.DEBUG;
/**
* A {@code FileInputStream} obtains input bytes
* from a file in a file system. What files
@@ -88,20 +75,6 @@ public class FileInputStream extends InputStream
private volatile boolean closed;
// This field indicates whether the file is a regular file as some
// operations need the current position which requires seeking
private @Stable Boolean isRegularFile;
private final boolean useNio;
@SuppressWarnings({
"FieldCanBeLocal",
"this-escape", // It immediately converts into a phantom reference.
})
private final NioChannelCleanable channelCleanable = new NioChannelCleanable(this);
private final ExternalChannelHolder externalChannelHolder;
/**
* Creates a {@code FileInputStream} by
* opening a connection to an actual file,
@@ -173,40 +146,11 @@ public class FileInputStream extends InputStream
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
path = file.getPath();
java.nio.file.FileSystem nioFs = IoOverNioFileSystem.acquireNioFs(path);
Path nioPath = null;
if (nioFs != null && path != null) {
try {
nioPath = nioFs.getPath(path);
isRegularFile = Files.isRegularFile(nioPath);
} catch (InvalidPathException|SecurityException ignored) {
// Nothing.
}
}
// Two significant differences between the legacy java.io and java.nio.files:
// * java.nio.file allows to open directories as streams, java.io.FileInputStream doesn't.
// * java.nio.file doesn't work well with pseudo devices, i.e., `seek()` fails, while java.io works well.
useNio = nioPath != null && isRegularFile == Boolean.TRUE;
if (useNio) {
var bundle = IoOverNioFileSystem.initializeStreamUsingNio(
this, nioFs, file, nioPath, Set.of(StandardOpenOption.READ), channelCleanable);
channel = bundle.channel();
fd = bundle.fd();
externalChannelHolder = bundle.externalChannelHolder();
} else {
fd = new FileDescriptor();
fd.attach(this);
open(path);
FileCleanable.register(fd); // open set the fd, register the cleanup
externalChannelHolder = null;
}
if (DEBUG.writeTraces()) {
System.err.printf("Created a FileInputStream for %s%n", file);
}
fd = new FileDescriptor();
fd.attach(this);
path = name;
open(name);
FileCleanable.register(fd); // open set the fd, register the cleanup
}
/**
@@ -234,9 +178,6 @@ public class FileInputStream extends InputStream
* @see SecurityManager#checkRead(java.io.FileDescriptor)
*/
public FileInputStream(FileDescriptor fdObj) {
useNio = false;
externalChannelHolder = null;
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (fdObj == null) {
@@ -287,7 +228,7 @@ public class FileInputStream extends InputStream
public int read() throws IOException {
long comp = Blocker.begin();
try {
return implRead();
return read0();
} finally {
Blocker.end(comp);
}
@@ -295,17 +236,6 @@ public class FileInputStream extends InputStream
private native int read0() throws IOException;
private int implRead() throws IOException {
if (!useNio) {
return read0();
} else {
ByteBuffer buffer = ByteBuffer.allocate(1);
int nRead = channel.read(buffer);
buffer.rewind();
return nRead == 1 ? (buffer.get() & 0xFF) : -1;
}
}
/**
* Reads a subarray as a sequence of bytes.
* @param b the data to be written
@@ -330,26 +260,12 @@ public class FileInputStream extends InputStream
public int read(byte[] b) throws IOException {
long comp = Blocker.begin();
try {
return implRead(b);
return readBytes(b, 0, b.length);
} finally {
Blocker.end(comp);
}
}
private int implRead(byte[] b) throws IOException {
if (!useNio) {
return readBytes(b, 0, b.length);
} else {
try {
ByteBuffer buffer = ByteBuffer.wrap(b);
return channel.read(buffer);
} catch (OutOfMemoryError e) {
// May fail to allocate direct buffer memory due to small -XX:MaxDirectMemorySize
return readBytes(b, 0, b.length);
}
}
}
/**
* Reads up to {@code len} bytes of data from this input stream
* into an array of bytes. If {@code len} is not zero, the method
@@ -368,26 +284,12 @@ public class FileInputStream extends InputStream
public int read(byte[] b, int off, int len) throws IOException {
long comp = Blocker.begin();
try {
return implRead(b, off, len);
return readBytes(b, off, len);
} finally {
Blocker.end(comp);
}
}
private int implRead(byte[] b, int off, int len) throws IOException {
if (!useNio) {
return readBytes(b, off, len);
} else {
try {
ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
return channel.read(buffer);
} catch (OutOfMemoryError e) {
// May fail to allocate direct buffer memory due to small -XX:MaxDirectMemorySize
return readBytes(b, off, len);
}
}
}
@Override
public byte[] readAllBytes() throws IOException {
long length = length();
@@ -474,8 +376,8 @@ public class FileInputStream extends InputStream
@Override
public long transferTo(OutputStream out) throws IOException {
long transferred = 0L;
if (out instanceof FileOutputStream fos && isRegularFile != Boolean.FALSE) {
FileChannel fc = useNio ? channel : getChannel();
if (out instanceof FileOutputStream fos) {
FileChannel fc = getChannel();
long pos = fc.position();
transferred = fc.transferTo(pos, Long.MAX_VALUE, fos.getChannel());
long newPos = pos + transferred;
@@ -494,11 +396,7 @@ public class FileInputStream extends InputStream
private long length() throws IOException {
long comp = Blocker.begin();
try {
if (!useNio) {
return length0();
} else {
return channel.size();
}
return length0();
} finally {
Blocker.end(comp);
}
@@ -508,11 +406,7 @@ public class FileInputStream extends InputStream
private long position() throws IOException {
long comp = Blocker.begin();
try {
if (!useNio) {
return position0();
} else {
return channel.position();
}
return position0();
} finally {
Blocker.end(comp);
}
@@ -547,15 +441,7 @@ public class FileInputStream extends InputStream
public long skip(long n) throws IOException {
long comp = Blocker.begin();
try {
if (isRegularFile == Boolean.FALSE) {
return super.skip(n);
} else if (!useNio) {
return skip0(n);
} else {
long startPos = channel.position();
channel.position(startPos + n);
return channel.position() - startPos;
}
return skip0(n);
} finally {
Blocker.end(comp);
}
@@ -584,14 +470,7 @@ public class FileInputStream extends InputStream
public int available() throws IOException {
long comp = Blocker.begin();
try {
if (!useNio) {
return available0();
} else {
long size = channel.size();
long pos = channel.position();
long avail = size > pos ? (size - pos) : 0;
return avail > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)avail;
}
return available0();
} finally {
Blocker.end(comp);
}
@@ -642,10 +521,6 @@ public class FileInputStream extends InputStream
fc.close();
}
if (externalChannelHolder != null) {
externalChannelHolder.close();
}
fd.closeAll(new Closeable() {
public void close() throws IOException {
fd.close();
@@ -686,10 +561,6 @@ public class FileInputStream extends InputStream
* @since 1.4
*/
public FileChannel getChannel() {
if (externalChannelHolder != null) {
return externalChannelHolder.getInterruptibleChannel();
}
FileChannel fc = this.channel;
if (fc == null) {
synchronized (this) {
@@ -717,12 +588,4 @@ public class FileInputStream extends InputStream
static {
initIDs();
}
/**
* This method is called by JFR. See {@code FileInputStreamInstrumentor.java}.
*/
@SuppressWarnings("unused")
private boolean ioOverNioInThisThread() {
return IoOverNio.isAllowedInThisThread();
}
}

View File

@@ -25,22 +25,11 @@
package java.io;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.DosFileAttributeView;
import java.nio.file.attribute.DosFileAttributes;
import java.util.Set;
import com.jetbrains.internal.IoOverNio;
import jdk.internal.access.SharedSecrets;
import jdk.internal.access.JavaIOFileDescriptorAccess;
import jdk.internal.misc.Blocker;
import sun.nio.ch.FileChannelImpl;
import static com.jetbrains.internal.IoOverNio.DEBUG;
/**
@@ -100,16 +89,6 @@ public class FileOutputStream extends OutputStream
private volatile boolean closed;
private final boolean useNio;
@SuppressWarnings({
"FieldCanBeLocal",
"this-escape", // It immediately converts into a phantom reference.
})
private final NioChannelCleanable channelCleanable = new NioChannelCleanable(this);
private final ExternalChannelHolder externalChannelHolder;
/**
* Creates a file output stream to write to the file with the
* specified name. A new {@code FileDescriptor} object is
@@ -229,7 +208,6 @@ public class FileOutputStream extends OutputStream
* @see java.lang.SecurityManager#checkWrite(java.lang.String)
* @since 1.4
*/
@SuppressWarnings("this-escape")
public FileOutputStream(File file, boolean append)
throws FileNotFoundException
{
@@ -245,48 +223,12 @@ public class FileOutputStream extends OutputStream
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
this.fd = new FileDescriptor();
fd.attach(this);
this.path = name;
java.nio.file.FileSystem nioFs = IoOverNioFileSystem.acquireNioFs(path);
useNio = path != null && nioFs != null;
if (useNio) {
Path nioPath = nioFs.getPath(path);
// java.io backend doesn't open DOS hidden files for writing, but java.nio.file opens.
// This code mimics the old behavior.
if (nioFs.getSeparator().equals("\\")) {
DosFileAttributes attrs = null;
try {
var view = Files.getFileAttributeView(nioPath, DosFileAttributeView.class);
if (view != null) {
attrs = view.readAttributes();
}
} catch (IOException | UnsupportedOperationException | SecurityException ignored) {
// Windows paths without DOS attributes? Not a problem in this case.
}
if (attrs != null && (attrs.isHidden() || attrs.isDirectory())) {
throw new FileNotFoundException(file.getPath() + " (Access is denied)");
}
}
Set<OpenOption> options = append
? Set.of(StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND)
: Set.of(StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
var bundle = IoOverNioFileSystem.initializeStreamUsingNio(
this, nioFs, file, nioPath, options, channelCleanable);
channel = bundle.channel();
fd = bundle.fd();
externalChannelHolder = bundle.externalChannelHolder();
} else {
this.fd = new FileDescriptor();
fd.attach(this);
open(name, append);
FileCleanable.register(fd); // open sets the fd, register the cleanup
externalChannelHolder = null;
}
if (DEBUG.writeTraces()) {
System.err.printf("Created a FileOutputStream for %s%n", file);
}
open(name, append);
FileCleanable.register(fd); // open sets the fd, register the cleanup
}
/**
@@ -313,9 +255,6 @@ public class FileOutputStream extends OutputStream
* @see java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)
*/
public FileOutputStream(FileDescriptor fdObj) {
useNio = false;
externalChannelHolder = null;
@SuppressWarnings("removal")
SecurityManager security = System.getSecurityManager();
if (fdObj == null) {
@@ -374,26 +313,12 @@ public class FileOutputStream extends OutputStream
boolean append = FD_ACCESS.getAppend(fd);
long comp = Blocker.begin();
try {
implWrite(b, append);
write(b, append);
} finally {
Blocker.end(comp);
}
}
private void implWrite(int b, boolean append) throws IOException {
if (!useNio) {
write(b, append);
} else {
// 'append' is ignored; the channel is supposed to obey the mode in which the file was opened
byte[] array = new byte[1];
array[0] = (byte) b;
ByteBuffer buffer = ByteBuffer.wrap(array);
do {
channel.write(buffer);
} while (buffer.hasRemaining());
}
}
/**
* Writes a sub array as a sequence of bytes.
* @param b the data to be written
@@ -418,7 +343,7 @@ public class FileOutputStream extends OutputStream
boolean append = FD_ACCESS.getAppend(fd);
long comp = Blocker.begin();
try {
implWriteBytes(b, 0, b.length, append);
writeBytes(b, 0, b.length, append);
} finally {
Blocker.end(comp);
}
@@ -439,29 +364,12 @@ public class FileOutputStream extends OutputStream
boolean append = FD_ACCESS.getAppend(fd);
long comp = Blocker.begin();
try {
implWriteBytes(b, off, len, append);
writeBytes(b, off, len, append);
} finally {
Blocker.end(comp);
}
}
private void implWriteBytes(byte[] b, int off, int len, boolean append) throws IOException {
if (!useNio) {
writeBytes(b, off, len, append);
} else {
// 'append' is ignored; the channel is supposed to obey the mode in which the file was opened
try {
ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
do {
channel.write(buffer);
} while (buffer.hasRemaining());
} catch (OutOfMemoryError e) {
// May fail to allocate direct buffer memory due to small -XX:MaxDirectMemorySize
writeBytes(b, off, len, append);
}
}
}
/**
* Closes this file output stream and releases any system resources
* associated with this stream. This file output stream may no longer
@@ -506,10 +414,6 @@ public class FileOutputStream extends OutputStream
fc.close();
}
if (externalChannelHolder != null) {
externalChannelHolder.close();
}
fd.closeAll(new Closeable() {
public void close() throws IOException {
fd.close();
@@ -551,10 +455,6 @@ public class FileOutputStream extends OutputStream
* @since 1.4
*/
public FileChannel getChannel() {
if (externalChannelHolder != null) {
return externalChannelHolder.getInterruptibleChannel();
}
FileChannel fc = this.channel;
if (fc == null) {
synchronized (this) {
@@ -582,12 +482,4 @@ public class FileOutputStream extends OutputStream
static {
initIDs();
}
/**
* This method is called by JFR. See {@code FileOutputStreamInstrumentor.java}.
*/
@SuppressWarnings("unused")
private boolean ioOverNioInThisThread() {
return IoOverNio.isAllowedInThisThread();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,78 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 java.io;
import jdk.internal.ref.CleanerFactory;
import jdk.internal.ref.PhantomCleanable;
import java.lang.ref.WeakReference;
import java.nio.channels.FileChannel;
/**
* Cleanable for {@link FileInputStream}, {@link FileOutputStream} and {@link RandomAccessFile}
* which is in use if {@link com.jetbrains.internal.IoOverNio#IS_ENABLED_IN_GENERAL} is true.
* <p>
* Implicitly, there MAY be used both this cleaner and {@link FileCleanable} for the same file descriptor,
* when the channel is {@link sun.nio.ch.FileChannelImpl}.
* However, this class is also able to close other channels.
*
* @see FileCleanable
*/
final class NioChannelCleanable extends PhantomCleanable<Object> {
private WeakReference<FileChannel> channel = new WeakReference<>(null);
/**
* @param channelOwner The owner of a channel.
* It is supposed to be {@link FileInputStream}, {@link FileOutputStream} or {@link RandomAccessFile}.
*/
NioChannelCleanable(Object channelOwner) {
super(channelOwner, CleanerFactory.cleaner());
assert channelOwner instanceof FileInputStream ||
channelOwner instanceof FileOutputStream ||
channelOwner instanceof RandomAccessFile
: channelOwner.getClass() + " is not an expected class";
}
/**
* The same as {@link FileCleanable#register} but for channels.
*/
void setChannel(FileChannel channel) {
this.channel = new WeakReference<>(channel);
}
@Override
protected void performCleanup() {
var channel = this.channel.get();
if (channel != null) {
try {
channel.close();
} catch (IOException | RuntimeException ignored) {
// Ignored.
}
}
}
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 java.io;
import jdk.internal.ref.CleanerFactory;
import jdk.internal.ref.PhantomCleanable;
/**
* An analog of {@link FileCleanable} that does nothing.
* <p>
* It exists only to fulfill an implicit contract that every {@link FileDescriptor}
* from {@link RandomAccessFile} and classes like that
* has a registered cleaner.
* Some tests rely on this contract and fail without this class.
*/
class NoOpCleanable extends PhantomCleanable<FileDescriptor> {
NoOpCleanable(FileDescriptor referent) {
super(referent, CleanerFactory.cleaner());
}
@Override
protected void performCleanup() {
// Nothing.
}
}

View File

@@ -25,38 +25,14 @@
package java.io;
import com.jetbrains.internal.IoOverNio;
import java.nio.channels.FileChannel;
import jdk.internal.access.JavaIORandomAccessFileAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.Blocker;
import jdk.internal.util.ByteArray;
import sun.nio.ch.FileChannelImpl;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Objects;
import java.nio.channels.NonWritableChannelException;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.HashSet;
import static com.jetbrains.internal.IoOverNio.DEBUG;
/**
* Instances of this class support both reading and writing to a
@@ -114,16 +90,6 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
private volatile FileChannel channel;
private volatile boolean closed;
private final boolean useNio;
@SuppressWarnings({
"FieldCanBeLocal",
"this-escape", // It immediately converts into a phantom reference.
})
private final NioChannelCleanable channelCleanable = new NioChannelCleanable(this);
private final ExternalChannelHolder externalChannelHolder;
/**
* Creates a random access file stream to read from, and optionally
* to write to, a file with the specified name. A new
@@ -301,63 +267,11 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
fd = new FileDescriptor();
fd.attach(this);
path = name;
FileSystem nioFs = IoOverNioFileSystem.acquireNioFs(path);
Path nioPath = null;
if (nioFs != null) {
try {
nioPath = nioFs.getPath(path);
} catch (InvalidPathException ignored) {
// Nothing.
}
}
// Two significant differences between the legacy java.io and java.nio.files:
// * java.nio.file allows to open directories as streams, java.io.FileInputStream doesn't.
// * java.nio.file doesn't work well with pseudo devices, i.e., `seek()` fails, while java.io works well.
boolean isRegularFile;
try {
isRegularFile = nioPath != null &&
Files.readAttributes(nioPath, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS).isRegularFile();
}
catch (NoSuchFileException ignored) {
isRegularFile = true;
}
catch (IOException ignored) {
isRegularFile = false;
}
useNio = nioPath != null && isRegularFile;
if (useNio) {
var bundle = IoOverNioFileSystem.initializeStreamUsingNio(
this, nioFs, file, nioPath, optionsForChannel(imode), channelCleanable);
channel = bundle.channel();
fd = bundle.fd();
externalChannelHolder = bundle.externalChannelHolder();
} else {
fd = new FileDescriptor();
fd.attach(this);
open(name, imode);
FileCleanable.register(fd); // open sets the fd, register the cleanup
externalChannelHolder = null;
}
if (DEBUG.writeTraces()) {
System.err.printf("Created a RandomAccessFile for %s%n", file);
}
}
private static HashSet<OpenOption> optionsForChannel(int imode) {
HashSet<OpenOption> options = new HashSet<>(6);
options.add(StandardOpenOption.READ);
if ((imode & O_RDONLY) == 0) {
options.add(StandardOpenOption.WRITE);
options.add(StandardOpenOption.CREATE);
}
if ((imode & O_SYNC) == O_SYNC) options.add(StandardOpenOption.SYNC);
if ((imode & O_DSYNC) == O_DSYNC) options.add(StandardOpenOption.DSYNC);
if ((imode & O_TEMPORARY) == O_TEMPORARY) options.add(StandardOpenOption.DELETE_ON_CLOSE);
IoOverNioOsSpecific.optionsForChannelInRandomAccessFile(options, imode);
return options;
open(name, imode);
FileCleanable.register(fd); // open sets the fd, register the cleanup
}
/**
@@ -390,10 +304,6 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* @since 1.4
*/
public final FileChannel getChannel() {
if (externalChannelHolder != null) {
return externalChannelHolder.getInterruptibleChannel();
}
FileChannel fc = this.channel;
if (fc == null) {
synchronized (this) {
@@ -469,23 +379,12 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
public int read() throws IOException {
long comp = Blocker.begin();
try {
return implRead();
return read0();
} finally {
Blocker.end(comp);
}
}
private int implRead() throws IOException {
if (!useNio) {
return read0();
} else {
ByteBuffer buffer = ByteBuffer.allocate(1);
int nRead = channel.read(buffer);
buffer.rewind();
return nRead == 1 ? (buffer.get() & 0xFF) : -1;
}
}
private native int read0() throws IOException;
/**
@@ -498,26 +397,12 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
private int readBytes(byte[] b, int off, int len) throws IOException {
long comp = Blocker.begin();
try {
return implReadBytes(b, off, len);
return readBytes0(b, off, len);
} finally {
Blocker.end(comp);
}
}
private int implReadBytes(byte[] b, int off, int len) throws IOException {
if (!useNio) {
return readBytes0(b, off, len);
} else {
try {
ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
return channel.read(buffer);
} catch (OutOfMemoryError e) {
// May fail to allocate direct buffer memory due to small -XX:MaxDirectMemorySize
return readBytes0(b, off, len);
}
}
}
private native int readBytes0(byte[] b, int off, int len) throws IOException;
/**
@@ -546,17 +431,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* {@code b.length - off}
*/
public int read(byte[] b, int off, int len) throws IOException {
if (!useNio) {
return readBytes(b, off, len);
} else {
try {
ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
return channel.read(buffer);
} catch (OutOfMemoryError e) {
// May fail to allocate direct buffer memory due to small -XX:MaxDirectMemorySize
return readBytes(b, off, len);
}
}
return readBytes(b, off, len);
}
/**
@@ -579,17 +454,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* @throws NullPointerException If {@code b} is {@code null}.
*/
public int read(byte[] b) throws IOException {
if (!useNio) {
return readBytes(b, 0, b.length);
} else {
try {
ByteBuffer buffer = ByteBuffer.wrap(b);
return channel.read(buffer);
} catch (OutOfMemoryError e) {
// May fail to allocate direct buffer memory due to small -XX:MaxDirectMemorySize
return readBytes(b, 0, b.length);
}
}
return readBytes(b, 0, b.length);
}
/**
@@ -685,29 +550,12 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
public void write(int b) throws IOException {
long comp = Blocker.begin();
try {
implWrite(b);
write0(b);
} finally {
Blocker.end(comp);
}
}
private void implWrite(int b) throws IOException {
if (!useNio) {
write0(b);
} else {
byte[] array = new byte[1];
array[0] = (byte) b;
ByteBuffer buffer = ByteBuffer.wrap(array);
do {
try {
channel.write(buffer);
} catch (java.nio.channels.NonWritableChannelException err) {
throw new IOException("Bad file descriptor", err);
}
} while (buffer.hasRemaining());
}
}
private native void write0(int b) throws IOException;
/**
@@ -721,32 +569,12 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
private void writeBytes(byte[] b, int off, int len) throws IOException {
long comp = Blocker.begin();
try {
implWriteBytes(b, off, len);
writeBytes0(b, off, len);
} finally {
Blocker.end(comp);
}
}
private void implWriteBytes(byte[] b, int off, int len) throws IOException {
if (!useNio) {
writeBytes0(b, off, len);
} else {
try {
ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
do {
try {
channel.write(buffer);
} catch (java.nio.channels.NonWritableChannelException err) {
throw new IOException("Bad file descriptor", err);
}
} while (buffer.hasRemaining());
} catch (OutOfMemoryError e) {
// May fail to allocate direct buffer memory due to small -XX:MaxDirectMemorySize
writeBytes0(b, off, len);
}
}
}
private native void writeBytes0(byte[] b, int off, int len) throws IOException;
/**
@@ -783,15 +611,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* at which the next read or write occurs.
* @throws IOException if an I/O error occurs.
*/
public long getFilePointer() throws IOException {
if (!useNio) {
return getFilePointer0();
} else {
return channel.position();
}
}
private native long getFilePointer0() throws IOException;
public native long getFilePointer() throws IOException;
/**
* Sets the file-pointer offset, measured from the beginning of this
@@ -813,11 +633,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
long comp = Blocker.begin();
try {
if (!useNio) {
seek0(pos);
} else {
channel.position(pos);
}
seek0(pos);
} finally {
Blocker.end(comp);
}
@@ -834,11 +650,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
public long length() throws IOException {
long comp = Blocker.begin();
try {
if (!useNio) {
return length0();
} else {
return channel.size();
}
return length0();
} finally {
Blocker.end(comp);
}
@@ -868,39 +680,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
public void setLength(long newLength) throws IOException {
long comp = Blocker.begin();
try {
if (!useNio) {
setLength0(newLength);
} else {
try {
long oldSize = channel.size();
if (newLength < oldSize) {
channel.truncate(newLength);
} else {
long position = channel.position();
channel.position(channel.size());
try {
byte[] buf = new byte[1 << 14];
Arrays.fill(buf, (byte) 0);
long remains = newLength - oldSize;
while (remains > 0) {
ByteBuffer buffer = ByteBuffer.wrap(buf);
int length = (int) Math.min(remains, buf.length);
buffer.limit(length);
int written = channel.write(buffer);
remains -= written;
}
} finally {
try {
channel.position(position);
} catch (IOException ignored) {
// Nothing.
}
}
}
} catch (NonWritableChannelException err) {
throw new IOException("setLength failed", err);
}
}
setLength0(newLength);
} finally {
Blocker.end(comp);
}
@@ -944,10 +724,6 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
fc.close();
}
if (externalChannelHolder != null) {
externalChannelHolder.close();
}
fd.closeAll(new Closeable() {
public void close() throws IOException {
fd.close();
@@ -1458,12 +1234,4 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
});
}
/**
* This method is called by JFR. See {@code RandomAccessFileInstrumentor.java}.
*/
@SuppressWarnings("unused")
private boolean ioOverNioInThisThread() {
return IoOverNio.isAllowedInThisThread();
}
}

View File

@@ -36,7 +36,6 @@ import java.util.Map;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import com.jetbrains.internal.IoOverNio;
import jdk.internal.loader.ClassLoaders;
import jdk.internal.misc.VM;
import sun.nio.fs.DefaultFileSystemProvider;
@@ -96,14 +95,7 @@ public final class FileSystems {
static final FileSystem defaultFileSystem = defaultFileSystem();
// returns default file system
@SuppressWarnings("try")
private static FileSystem defaultFileSystem() {
try (var ignored = IoOverNio.disableInThisThread()) {
return defaultFileSystem0();
}
}
private static FileSystem defaultFileSystem0() {
// load default provider
@SuppressWarnings("removal")
FileSystemProvider provider = AccessController

View File

@@ -31,7 +31,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.io.*;
import java.net.URL;
import com.jetbrains.internal.IoOverNio;
import jdk.internal.access.JavaSecurityPropertiesAccess;
import jdk.internal.event.EventHelper;
import jdk.internal.event.SecurityPropertyModificationEvent;
@@ -94,14 +93,7 @@ public final class Security {
});
}
@SuppressWarnings("try")
private static void initialize() {
try (var ignored = IoOverNio.disableInThisThread()) {
initialize0();
}
}
private static void initialize0() {
props = new Properties();
boolean overrideAll = false;
@@ -131,6 +123,7 @@ public final class Security {
props.getProperty(key));
}
}
}
private static boolean loadProps(File masterFile, String extraPropFile, boolean overrideAll) {

View File

@@ -41,7 +41,6 @@ import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import java.util.stream.Stream;
import com.jetbrains.internal.IoOverNio;
import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.module.Modules;
@@ -144,19 +143,17 @@ public class BootLoader {
/**
* Loads a native library from the system library path.
*/
@SuppressWarnings({"try", "removal"})
@SuppressWarnings("removal")
public static void loadLibrary(String name) {
try (var ignored = IoOverNio.disableInThisThread()) {
if (System.getSecurityManager() == null) {
BootLoader.getNativeLibraries().loadLibrary(name);
} else {
AccessController.doPrivileged(new java.security.PrivilegedAction<>() {
public Void run() {
BootLoader.getNativeLibraries().loadLibrary(name);
return null;
}
});
}
if (System.getSecurityManager() == null) {
BootLoader.getNativeLibraries().loadLibrary(name);
} else {
AccessController.doPrivileged(new java.security.PrivilegedAction<>() {
public Void run() {
BootLoader.getNativeLibraries().loadLibrary(name);
return null;
}
});
}
}

View File

@@ -57,7 +57,6 @@ import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.stream.Stream;
import com.jetbrains.internal.IoOverNio;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.VM;
import jdk.internal.module.ModulePatcher.PatchedModuleReader;
@@ -736,15 +735,13 @@ public class BuiltinClassLoader
*
* @return the resulting Class or {@code null} if not found
*/
@SuppressWarnings({"removal", "try"})
@SuppressWarnings("removal")
private Class<?> findClassInModuleOrNull(LoadedModule loadedModule, String cn) {
try (var ignored = IoOverNio.disableInThisThread()) {
if (System.getSecurityManager() == null) {
return defineClass(cn, loadedModule);
} else {
PrivilegedAction<Class<?>> pa = () -> defineClass(cn, loadedModule);
return AccessController.doPrivileged(pa);
}
if (System.getSecurityManager() == null) {
return defineClass(cn, loadedModule);
} else {
PrivilegedAction<Class<?>> pa = () -> defineClass(cn, loadedModule);
return AccessController.doPrivileged(pa);
}
}
@@ -753,37 +750,35 @@ public class BuiltinClassLoader
*
* @return the resulting Class or {@code null} if not found
*/
@SuppressWarnings({"removal", "try"})
@SuppressWarnings("removal")
private Class<?> findClassOnClassPathOrNull(String cn) {
String path = cn.replace('.', '/').concat(".class");
try (var ignored = IoOverNio.disableInThisThread()) {
if (System.getSecurityManager() == null) {
Resource res = ucp.getResource(path, false);
if (res != null) {
try {
return defineClass(cn, res);
} catch (IOException ioe) {
// TBD on how I/O errors should be propagated
}
if (System.getSecurityManager() == null) {
Resource res = ucp.getResource(path, false);
if (res != null) {
try {
return defineClass(cn, res);
} catch (IOException ioe) {
// TBD on how I/O errors should be propagated
}
return null;
} else {
// avoid use of lambda here
PrivilegedAction<Class<?>> pa = new PrivilegedAction<>() {
public Class<?> run() {
Resource res = ucp.getResource(path, false);
if (res != null) {
try {
return defineClass(cn, res);
} catch (IOException ioe) {
// TBD on how I/O errors should be propagated
}
}
return null;
}
};
return AccessController.doPrivileged(pa);
}
return null;
} else {
// avoid use of lambda here
PrivilegedAction<Class<?>> pa = new PrivilegedAction<>() {
public Class<?> run() {
Resource res = ucp.getResource(path, false);
if (res != null) {
try {
return defineClass(cn, res);
} catch (IOException ioe) {
// TBD on how I/O errors should be propagated
}
}
return null;
}
};
return AccessController.doPrivileged(pa);
}
}

View File

@@ -24,7 +24,6 @@
*/
package jdk.internal.loader;
import com.jetbrains.internal.IoOverNio;
import jdk.internal.misc.VM;
import jdk.internal.ref.CleanerFactory;
import jdk.internal.util.StaticProperty;
@@ -33,8 +32,6 @@ import java.io.File;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.function.BiFunction;
@@ -117,16 +114,15 @@ public final class NativeLibraries {
* @param file the path of the native library
* @throws UnsatisfiedLinkError if any error in loading the native library
*/
@SuppressWarnings({"try", "removal"})
@SuppressWarnings("removal")
public NativeLibrary loadLibrary(Class<?> fromClass, File file) {
// Check to see if we're attempting to access a static library
String name = findBuiltinLib(file.getName());
boolean isBuiltin = (name != null);
if (!isBuiltin) {
name = AccessController.doPrivileged(new PrivilegedAction<>() {
@SuppressWarnings("try")
public String run() {
try(var ignored = IoOverNio.disableInThisThread()) {
try {
if (loadLibraryOnlyIfPresent && !file.exists()) {
return null;
}
@@ -342,12 +338,9 @@ public final class NativeLibraries {
// If the file exists but fails to load, UnsatisfiedLinkException thrown by the VM
// will include the error message from dlopen to provide diagnostic information
return AccessController.doPrivileged(new PrivilegedAction<>() {
@SuppressWarnings("try")
public Boolean run() {
try (var ignored = IoOverNio.disableInThisThread()) {
File file = new File(name);
return file.exists();
}
File file = new File(name);
return file.exists();
}
});
}

View File

@@ -47,7 +47,6 @@ import java.nio.channels.SelectableChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Objects;
import com.jetbrains.internal.IoOverNio;
import jdk.internal.access.JavaIOFileDescriptorAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.foreign.AbstractMemorySegmentImpl;
@@ -130,9 +129,6 @@ public class FileChannelImpl
this.readable = readable;
this.writable = writable;
this.direct = direct;
if (parent == null) {
parent = IoOverNio.PARENT_FOR_FILE_CHANNEL_IMPL.get();
}
this.parent = parent;
if (direct) {
assert path != null;
@@ -168,24 +164,6 @@ public class FileChannelImpl
uninterruptible = true;
}
public void setInterruptible() {
uninterruptible = false;
}
@Override
public FileChannelImpl clone() {
FileChannelImpl result = new FileChannelImpl(fd, path, readable, writable, direct, parent);
result.uninterruptible = uninterruptible;
if (!isOpen()) {
try {
result.close();
} catch (IOException ignored) {
// Ignored.
}
}
return result;
}
private void beginBlocking() {
if (!uninterruptible) begin();
}
@@ -1581,8 +1559,4 @@ public class FileChannelImpl
assert fileLockTable != null;
fileLockTable.remove(fli);
}
public FileDescriptor getFD() {
return fd;
}
}

View File

@@ -41,8 +41,6 @@ import javax.security.auth.x500.X500Principal;
import java.net.SocketPermission;
import java.net.NetPermission;
import java.util.concurrent.ConcurrentHashMap;
import com.jetbrains.internal.IoOverNio;
import jdk.internal.access.JavaSecurityAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.util.StaticProperty;
@@ -310,14 +308,7 @@ public class PolicyFile extends java.security.Policy {
* See the class description for details on the algorithm used to
* initialize the Policy object.
*/
@SuppressWarnings("try")
private void init(URL url) {
try (var ignored = IoOverNio.disableInThisThread()) {
init0(url);
}
}
private void init0(URL url) {
// Properties are set once for each init(); ignore changes
// between diff invocations of initPolicyFile(policy, url, info).
String numCacheStr =
@@ -1102,16 +1093,8 @@ public class PolicyFile extends java.security.Policy {
*
* @return the set of Permissions according to the policy.
*/
@SuppressWarnings("try")
private PermissionCollection getPermissions(Permissions perms,
ProtectionDomain pd ) {
try (var ignored = IoOverNio.disableInThisThread()) {
return getPermissions0(perms, pd);
}
}
private Permissions getPermissions0(Permissions perms,
ProtectionDomain pd) {
if (debug != null) {
debug.println("getPermissions:\n\t" + printPD(pd));
}

View File

@@ -90,7 +90,7 @@ Java_java_io_RandomAccessFile_writeBytes0(JNIEnv *env,
}
JNIEXPORT jlong JNICALL
Java_java_io_RandomAccessFile_getFilePointer0(JNIEnv *env, jobject this) {
Java_java_io_RandomAccessFile_getFilePointer(JNIEnv *env, jobject this) {
FD fd;
jlong ret;

View File

@@ -1,35 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 java.io;
import java.nio.file.OpenOption;
import java.util.Set;
class IoOverNioOsSpecific {
static void optionsForChannelInRandomAccessFile(Set<OpenOption> options, int imode) {
// Nothing.
}
}

View File

@@ -199,9 +199,8 @@ class UnixChannelFactory {
if (flags.createNew) {
byte[] pathForSysCall = path.getByteArrayForSysCalls();
// throw exception if file name is "." or "" to avoid confusing error
if ((pathForSysCall.length == 0) ||
(pathForSysCall[pathForSysCall.length-1] == '.') &&
// throw exception if file name is "." to avoid confusing error
if ((pathForSysCall[pathForSysCall.length-1] == '.') &&
(pathForSysCall.length == 1 ||
(pathForSysCall[pathForSysCall.length-2] == '/')))
{

View File

@@ -25,8 +25,6 @@
package sun.nio.fs;
import com.jetbrains.internal.IoToNioErrorMessageHolder;
import java.nio.file.*;
import java.io.IOException;
@@ -106,7 +104,6 @@ class UnixException extends Exception {
String a = (file == null) ? null : file.getPathForExceptionMessage();
String b = (other == null) ? null : other.getPathForExceptionMessage();
IOException x = translateToIOException(a, b);
IoToNioErrorMessageHolder.addMessage(x, errorString());
throw x;
}
@@ -115,8 +112,6 @@ class UnixException extends Exception {
}
IOException asIOException(UnixPath file) {
IOException x = translateToIOException(file.getPathForExceptionMessage(), null);
IoToNioErrorMessageHolder.addMessage(x, errorString());
return x;
return translateToIOException(file.getPathForExceptionMessage(), null);
}
}

View File

@@ -30,7 +30,6 @@ import java.net.*;
import java.security.*;
import java.util.Arrays;
import com.jetbrains.internal.IoOverNio;
import sun.security.util.Debug;
/**
@@ -127,15 +126,8 @@ public final class NativePRNG extends SecureRandomSpi {
/**
* Create a RandomIO object for all I/O of this Variant type.
*/
@SuppressWarnings("try")
private static RandomIO initIO(final Variant v) {
try (var ignored = IoOverNio.disableInThisThread()) {
return initIOImpl(v);
}
}
@SuppressWarnings("removal")
private static RandomIO initIOImpl(final Variant v) {
private static RandomIO initIO(final Variant v) {
return AccessController.doPrivileged(
new PrivilegedAction<>() {
@Override

View File

@@ -1,35 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 java.io;
import java.nio.file.OpenOption;
import java.util.Set;
class IoOverNioOsSpecific {
static void optionsForChannelInRandomAccessFile(Set<OpenOption> options, int imode) {
options.add(JbExtendedOpenOptions.NOSHARE_DELETE);
}
}

View File

@@ -1,44 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 java.io;
import sun.nio.fs.ExtendedOptions;
import java.nio.file.OpenOption;
enum JbExtendedOpenOptions implements OpenOption {
/**
* The same as {@link com.sun.nio.file.ExtendedOpenOption#NOSHARE_DELETE}.
* <p>
* The original option can't be used because it resides in the module {@code jdk.unsupported},
* which depends on this module.
*/
NOSHARE_DELETE(ExtendedOptions.NOSHARE_DELETE);
JbExtendedOpenOptions(ExtendedOptions.InternalOption<Void> extendedOption) {
extendedOption.register(this);
}
}

View File

@@ -25,8 +25,6 @@
package sun.nio.fs;
import com.jetbrains.internal.IoToNioErrorMessageHolder;
import java.nio.file.*;
import java.io.IOException;
@@ -96,7 +94,6 @@ class WindowsException extends Exception {
void rethrowAsIOException(String file) throws IOException {
IOException x = translateToIOException(file, null);
IoToNioErrorMessageHolder.addMessage(x, errorString());
throw x;
}
@@ -104,7 +101,6 @@ class WindowsException extends Exception {
String a = (file == null) ? null : file.getPathForExceptionMessage();
String b = (other == null) ? null : other.getPathForExceptionMessage();
IOException x = translateToIOException(a, b);
IoToNioErrorMessageHolder.addMessage(x, errorString());
throw x;
}

View File

@@ -24,101 +24,74 @@
*/
package sun.awt.wl;
import jdk.internal.misc.InnocuousThread;
import sun.awt.datatransfer.DataTransferer;
import sun.awt.datatransfer.SunClipboard;
import sun.util.logging.PlatformLogger;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.FlavorTable;
import java.awt.datatransfer.Transferable;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.SortedMap;
public final class WLClipboard extends SunClipboard {
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.WLClipboard");
public static final int INITIAL_MIME_FORMATS_COUNT = 10;
private static final int DEFAULT_BUFFER_SIZE = 4096;
private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
// A native handle of a Wayland queue dedicated to handling
// data offer-related events
private static final long dataOfferQueuePtr;
private final long ID;
private final WLDataDevice dataDevice;
// true if this is the "primary selection" clipboard,
// false otherwise (the regular clipboard).
private final boolean isPrimary; // used by native
private final boolean isPrimary;
private final Object dataLock = new Object();
// A handle to the native clipboard representation, 0 if not available.
private long clipboardNativePtr; // guarded by dataLock
private long ourOfferNativePtr; // guarded by dataLock
// The list of numeric format IDs the current clipboard is available in;
// could be null or empty.
private List<Long> clipboardFormats; // guarded by dataLock
// Latest active data offer to us, containing up-to-date clipboard content,
// as provided by the Wayland compositor.
// If null, there's no clipboard data available.
// Guarded by dataLock.
private WLDataOffer clipboardDataOfferedToUs;
// The "current" list formats for the new clipboard contents that is about
// to be received from Wayland. Could be empty, but never null.
private List<Long> newClipboardFormats = new ArrayList<>(INITIAL_MIME_FORMATS_COUNT); // guarded by dataLock
// Clipboard data source we are providing to the Wayland compositor.
// If null, we are not offering any clipboard data at the moment.
// Guarded by dataLock.
private WLDataSource ourDataSource;
private static final Thread clipboardDispatcherThread;
static {
initIDs();
dataOfferQueuePtr = createDataOfferQueue();
flavorTable = DataTransferer.adaptFlavorMap(getDefaultFlavorTable());
Thread t = InnocuousThread.newThread(
"AWT-Wayland-clipboard-dispatcher",
WLClipboard::dispatchDataOfferQueue);
t.setDaemon(true);
t.start();
clipboardDispatcherThread = t;
}
private final static FlavorTable flavorTable;
public WLClipboard(String name, boolean isPrimary) {
public WLClipboard(WLDataDevice dataDevice, String name, boolean isPrimary) {
super(name);
this.ID = initNative(isPrimary);
this.isPrimary = isPrimary;
this.dataDevice = dataDevice;
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Clipboard: Created " + this);
}
}
private static void dispatchDataOfferQueue() {
dispatchDataOfferQueueImpl(dataOfferQueuePtr); // does not return until error or server disconnect
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Clipboard: data offer dispatcher exited");
private int getProtocol() {
if (isPrimary) {
return WLDataDevice.DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION;
} else {
return WLDataDevice.DATA_TRANSFER_PROTOCOL_WAYLAND;
}
}
@Override
public String toString() {
return String.format("Clipboard: Wayland %s (%x)", (isPrimary ? "selection clipboard" : "clipboard"), ID);
return String.format("Clipboard: Wayland %s", (isPrimary ? "selection clipboard" : "clipboard"));
}
@Override
public long getID() {
return ID;
return isPrimary ? 2 : 1;
}
/**
* Called when we loose ownership of the clipboard.
* Called when we lose ownership of the clipboard.
*/
@Override
protected void clearNativeContext() {
@@ -164,34 +137,20 @@ public final class WLClipboard extends SunClipboard {
notifyOfNewFormats(formats);
if (formats.length > 0) {
String[] mime = new String[formats.length];
for (int i = 0; i < formats.length; i++) {
mime[i] = wlDataTransferer.getNativeForFormat(formats[i]);
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Clipboard: formats mapping " + formats[i] + " -> " + mime[i]);
}
}
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Clipboard: Offering new contents (" + contents + ") in these MIME formats: " + Arrays.toString(mime));
log.fine("Clipboard: Offering new contents (" + contents + ")");
}
WLDataSource newOffer = null;
newOffer = dataDevice.createDataSourceFromTransferable(getProtocol(), contents);
synchronized (dataLock) {
if (ourOfferNativePtr != 0) {
cancelOffer(ourOfferNativePtr);
ourOfferNativePtr = 0;
if (ourDataSource != null) {
ourDataSource.destroy();
}
ourDataSource = newOffer;
dataDevice.setSelection(getProtocol(), newOffer, eventSerial);
}
long newOfferPtr = offerData(eventSerial, mime, contents, dataOfferQueuePtr);
synchronized (dataLock) {
ourOfferNativePtr = newOfferPtr;
}
// Once we have offered the data, someone may come back and ask to provide them.
// In that event, the transferContentsWithType() will be called from native on the
// clipboard dispatch thread.
// A reference to contents is retained until we are notified of the new contents
// by the Wayland server.
}
} else {
this.owner = null;
@@ -200,74 +159,27 @@ public final class WLClipboard extends SunClipboard {
}
/**
* Called from native on EDT when a client has asked to provide the actual data for
* the clipboard that we own in the given format to the given file.
* NB: that client could be us, but we aren't necessarily aware of that once we
* lost keyboard focus at least once after Ctrl-C.
* Returns zero-length array (not null) if the number of available formats is zero.
*
* @param contents a reference to the clipboard's contents to be transferred
* @param mime transfer the contents in this MIME format
* @param destFD transfer the contents to this file descriptor and close it afterward
*
* @throws IOException in case writing to the given file descriptor failed
*/
private void transferContentsWithType(Transferable contents, String mime, int destFD) throws IOException {
assert (Thread.currentThread() == clipboardDispatcherThread);
Objects.requireNonNull(contents);
Objects.requireNonNull(mime);
WLDataTransferer wlDataTransferer = (WLDataTransferer) DataTransferer.getInstance();
SortedMap<Long,DataFlavor> formatMap =
wlDataTransferer.getFormatsForTransferable(contents, flavorTable);
long targetFormat = wlDataTransferer.getFormatForNativeAsLong(mime);
DataFlavor flavor = formatMap.get(targetFormat);
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Clipboard: will write contents (" + contents + ") in format " + mime + " to fd=" + destFD);
log.fine("Clipboard: data flavor: " + flavor);
}
if (flavor != null) {
byte[] bytes = wlDataTransferer.translateTransferable(contents, flavor, targetFormat);
if (bytes == null) return;
FileDescriptor javaDestFD = new FileDescriptor();
jdk.internal.access.SharedSecrets.getJavaIOFileDescriptorAccess().set(javaDestFD, destFD);
try (var out = new FileOutputStream(javaDestFD)) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Clipboard: about to write " + bytes.length + " bytes to " + out);
}
FileChannel ch = out.getChannel();
ByteBuffer buffer = ByteBuffer.wrap(bytes);
// Need to write with retries because when a pipe is in the non-blocking mode
// writing more than its capacity (usually 16 pages or 64K) fails with EAGAIN.
// Since we receive destFD from the Wayland sever, we can't assume it
// to always be in the blocking mode.
while (buffer.hasRemaining()) {
ch.write(buffer);
}
}
}
}
/**
* @return formats the current clipboard is available in; could be null
* @throws IllegalStateException if formats could not be retrieved
*/
@Override
protected long[] getClipboardFormats() {
WLDataTransferer wlDataTransferer = (WLDataTransferer) DataTransferer.getInstance();
List<String> mimes;
synchronized (dataLock) {
if (clipboardFormats != null && !clipboardFormats.isEmpty()) {
long[] res = new long[clipboardFormats.size()];
for (int i = 0; i < res.length; i++) {
res[i] = clipboardFormats.get(i);
}
return res;
} else {
return null;
if (clipboardDataOfferedToUs == null) {
return new long[0];
}
mimes = clipboardDataOfferedToUs.getMimes();
}
long[] formats = new long[mimes.size()];
for (int i = 0; i < mimes.size(); ++i) {
formats[i] = wlDataTransferer.getFormatForNativeAsLong(mimes.get(i));
}
return formats;
}
/**
@@ -279,100 +191,10 @@ public final class WLClipboard extends SunClipboard {
*/
@Override
protected byte[] getClipboardData(long format) throws IOException {
int fd = getClipboardFDIn(format);
if (fd >= 0) {
FileDescriptor javaFD = new FileDescriptor();
jdk.internal.access.SharedSecrets.getJavaIOFileDescriptorAccess().set(javaFD, fd);
try (var in = new FileInputStream(javaFD)) {
byte[] bytes = readAllBytesFrom(in);
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Clipboard: read data from " + fd + ": "
+ (bytes != null ? bytes.length : 0) + " bytes");
}
return bytes;
}
}
return null;
}
private int getClipboardFDIn(long format) {
synchronized (dataLock) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Clipboard: requested content of clipboard with handle "
+ clipboardNativePtr + " in format " + format);
}
if (clipboardNativePtr != 0) {
WLDataTransferer wlDataTransferer = (WLDataTransferer) DataTransferer.getInstance();
String mime = wlDataTransferer.getNativeForFormat(format);
int fd = requestDataInFormat(clipboardNativePtr, mime);
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Clipboard: will read data from " + fd + " in format " + mime);
}
return fd;
}
}
return -1;
}
/**
* Called from native to notify us of the availability of a new clipboard
* denoted by the native handle in a specific MIME format.
* This method is usually called repeatedly with the same nativePtr and
* different formats. When all formats are announces in this way,
* handleNewClipboard() is called.
*
* @param nativePtr a native handle to the clipboard
* @param mime the MIME format in which this clipboard is available.
*/
private void handleClipboardFormat(long nativePtr, String mime) {
WLDataTransferer wlDataTransferer = (WLDataTransferer) DataTransferer.getInstance();
Long format = wlDataTransferer.getFormatForNativeAsLong(mime);
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Clipboard: new format is available for " + nativePtr + ": " + mime);
}
String mime = wlDataTransferer.getNativeForFormat(format);
synchronized (dataLock) {
newClipboardFormats.add(format);
}
}
/**
* Called from native to notify us that a new clipboard content
* has been made available. The list of supported formats
* should have already been received and saved in newClipboardFormats.
*
* @param newClipboardNativePtr a native handle to the clipboard
*/
private void handleNewClipboard(long newClipboardNativePtr) {
// Since we have a new clipboard, the existing one is no longer valid.
// We have no way of knowing whether this "new" one is the same as the "old" one.
lostOwnershipNow(null);
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("Clipboard: new clipboard is available: " + newClipboardNativePtr);
}
synchronized (dataLock) {
long oldClipboardNativePtr = clipboardNativePtr;
if (oldClipboardNativePtr != 0) {
// "The client must destroy the previous selection data_offer, if any, upon receiving this event."
destroyClipboard(oldClipboardNativePtr);
}
clipboardFormats = newClipboardFormats;
clipboardNativePtr = newClipboardNativePtr; // Could be NULL
newClipboardFormats = new ArrayList<>(INITIAL_MIME_FORMATS_COUNT);
}
notifyOfNewFormats(getClipboardFormats());
}
private void handleOfferCancelled(long offerNativePtr) {
synchronized (dataLock) {
assert offerNativePtr == ourOfferNativePtr;
ourOfferNativePtr = 0;
return clipboardDataOfferedToUs.receiveData(mime);
}
}
@@ -397,76 +219,14 @@ public final class WLClipboard extends SunClipboard {
}
}
/**
* Reads the given input stream until EOF and returns its contents as an array of bytes.
*/
private byte[] readAllBytesFrom(FileInputStream inputStream) throws IOException {
int len = Integer.MAX_VALUE;
List<byte[]> bufs = null;
byte[] result = null;
int total = 0;
int remaining = len;
int n;
do {
byte[] buf = new byte[Math.min(remaining, DEFAULT_BUFFER_SIZE)];
int nread = 0;
void handleClipboardOffer(WLDataOffer offer /* nullable */) {
lostOwnershipNow(null);
while ((n = inputStream.read(buf, nread,
Math.min(buf.length - nread, remaining))) > 0) {
nread += n;
remaining -= n;
synchronized (dataLock) {
if (clipboardDataOfferedToUs != null) {
clipboardDataOfferedToUs.destroy();
}
if (nread > 0) {
if (MAX_BUFFER_SIZE - total < nread) {
throw new OutOfMemoryError("Required array size too large");
}
if (nread < buf.length) {
buf = Arrays.copyOfRange(buf, 0, nread);
}
total += nread;
if (result == null) {
result = buf;
} else {
if (bufs == null) {
bufs = new ArrayList<>();
bufs.add(result);
}
bufs.add(buf);
}
}
// if the last call to read returned -1 or the number of bytes
// requested have been read then break
} while (n >= 0 && remaining > 0);
if (bufs == null) {
if (result == null) {
return new byte[0];
}
return result.length == total ?
result : Arrays.copyOf(result, total);
clipboardDataOfferedToUs = offer;
}
result = new byte[total];
int offset = 0;
remaining = total;
for (byte[] b : bufs) {
int count = Math.min(b.length, remaining);
System.arraycopy(b, 0, result, offset, count);
offset += count;
remaining -= count;
}
return result;
}
private static native void initIDs();
private static native long createDataOfferQueue();
private static native void dispatchDataOfferQueueImpl(long dataOfferQueuePtr);
private native long initNative(boolean isPrimary);
private native long offerData(long eventSerial, String[] mime, Object data, long dataOfferQueuePtr);
private native void cancelOffer(long offerNativePtr);
private native int requestDataInFormat(long clipboardNativePtr, String mime);
private native void destroyClipboard(long clipboardNativePtr);
}

View File

@@ -0,0 +1,249 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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.awt.wl;
import jdk.internal.misc.InnocuousThread;
import sun.util.logging.PlatformLogger;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.SortedMap;
public class WLDataDevice {
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.WLDataDevice");
private long nativePtr;
private final WLClipboard systemClipboard;
private final WLClipboard primarySelectionClipboard;
public static final int DND_COPY = 0x01;
public static final int DND_MOVE = 0x02;
public static final int DND_ASK = 0x04;
public static final int DND_ALL = DND_COPY | DND_MOVE | DND_ASK;
public static final int DATA_TRANSFER_PROTOCOL_WAYLAND = 1;
public static final int DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION = 2;
WLDataDevice(long wlSeatNativePtr) {
nativePtr = initNative(wlSeatNativePtr);
var queueThread = InnocuousThread.newThread("AWT-Wayland-data-transferer-dispatcher", () -> {
dispatchDataTransferQueueImpl(nativePtr);
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("data transfer dispatcher exited");
}
});
queueThread.setDaemon(true);
queueThread.start();
systemClipboard = new WLClipboard(this, "System", false);
if (isProtocolSupported(DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION)) {
primarySelectionClipboard = new WLClipboard(this, "Selection", true);
} else {
primarySelectionClipboard = null;
}
}
private native static void initIDs();
static {
initIDs();
}
private native long initNative(long wlSeatNativePtr);
private static native boolean isProtocolSupportedImpl(long nativePtr, int protocol);
private static native void dispatchDataTransferQueueImpl(long nativePtr);
private static native void setSelectionImpl(int protocol, long nativePtr, long dataOfferNativePtr, long serial);
public WLDataSource createDataSourceFromTransferable(int protocol, Transferable transferable) {
return new WLDataSource(nativePtr, protocol, transferable);
}
public boolean isProtocolSupported(int protocol) {
return isProtocolSupportedImpl(nativePtr, protocol);
}
public void setSelection(int protocol, WLDataSource source, long serial) {
setSelectionImpl(protocol, nativePtr, source.getNativePtr(), serial);
}
public WLClipboard getSystemClipboard() {
return systemClipboard;
}
public WLClipboard getPrimarySelectionClipboard() {
return primarySelectionClipboard;
}
static void transferContentsWithType(Transferable contents, String mime, int fd) {
Objects.requireNonNull(contents);
Objects.requireNonNull(mime);
WLDataTransferer wlDataTransferer = (WLDataTransferer) WLDataTransferer.getInstance();
SortedMap<Long, DataFlavor> formatMap = wlDataTransferer.getFormatsForTransferable(contents, wlDataTransferer.getFlavorTable());
long targetFormat = wlDataTransferer.getFormatForNativeAsLong(mime);
DataFlavor flavor = formatMap.get(targetFormat);
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("will write contents (" + contents + ") in format " + mime + " to fd=" + fd);
log.fine("data flavor: " + flavor);
}
if (flavor != null) {
try {
byte[] bytes = wlDataTransferer.translateTransferable(contents, flavor, targetFormat);
if (bytes == null) return;
FileDescriptor javaDestFD = new FileDescriptor();
jdk.internal.access.SharedSecrets.getJavaIOFileDescriptorAccess().set(javaDestFD, fd);
try (var out = new FileOutputStream(javaDestFD)) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine("about to write " + bytes.length + " bytes to " + out);
}
FileChannel ch = out.getChannel();
ByteBuffer buffer = ByteBuffer.wrap(bytes);
// Need to write with retries because when a pipe is in the non-blocking mode
// writing more than its capacity (usually 16 pages or 64K) fails with EAGAIN.
// Since we receive fd from the Wayland sever, we can't assume it
// to always be in the blocking mode.
while (buffer.hasRemaining()) {
ch.write(buffer);
}
}
} catch (IOException e) {
log.warning("failed to write contents (" + contents + ") in format " + mime + " to fd=" + fd);
}
}
}
private static final int DEFAULT_BUFFER_SIZE = 4096;
private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
/**
* Reads the given input stream until EOF and returns its contents as an array of bytes.
*/
static byte[] readAllBytesFrom(FileInputStream inputStream) throws IOException {
int len = Integer.MAX_VALUE;
List<byte[]> bufs = null;
byte[] result = null;
int total = 0;
int remaining = len;
int n;
do {
byte[] buf = new byte[Math.min(remaining, DEFAULT_BUFFER_SIZE)];
int nread = 0;
while ((n = inputStream.read(buf, nread,
Math.min(buf.length - nread, remaining))) > 0) {
nread += n;
remaining -= n;
}
if (nread > 0) {
if (MAX_BUFFER_SIZE - total < nread) {
throw new OutOfMemoryError("Required array size too large");
}
if (nread < buf.length) {
buf = Arrays.copyOfRange(buf, 0, nread);
}
total += nread;
if (result == null) {
result = buf;
} else {
if (bufs == null) {
bufs = new ArrayList<>();
bufs.add(result);
}
bufs.add(buf);
}
}
// if the last call to read returned -1 or the number of bytes
// requested have been read then break
} while (n >= 0 && remaining > 0);
if (bufs == null) {
if (result == null) {
return new byte[0];
}
return result.length == total ?
result : Arrays.copyOf(result, total);
}
result = new byte[total];
int offset = 0;
remaining = total;
for (byte[] b : bufs) {
int count = Math.min(b.length, remaining);
System.arraycopy(b, 0, result, offset, count);
offset += count;
remaining -= count;
}
return result;
}
private WLDataOffer currentDnDOffer = null;
// Event handlers, called from native on the EDT
private void handleDnDEnter(WLDataOffer offer, long serial, long surfacePtr, double x, double y) {
if (currentDnDOffer != null) {
currentDnDOffer.destroy();
}
currentDnDOffer = offer;
}
private void handleDnDLeave() {
if (currentDnDOffer != null) {
currentDnDOffer.destroy();
currentDnDOffer = null;
}
}
private void handleDnDMotion(long timestamp, double x, double y) {
}
private void handleDnDDrop() {
}
private void handleSelection(WLDataOffer offer /* nullable */, int protocol) {
WLClipboard clipboard = (protocol == DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION) ? primarySelectionClipboard : systemClipboard;
if (clipboard != null) {
clipboard.handleClipboardOffer(offer);
}
}
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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.awt.wl;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class WLDataOffer {
private long nativePtr;
private final List<String> mimes = new ArrayList<>();
private int sourceActions = -1;
private int selectedAction = -1;
private static native void destroyImpl(long nativePtr);
private static native void acceptImpl(long nativePtr, long serial, String mime);
private static native int openReceivePipe(long nativePtr, String mime);
private static native void finishDnDImpl(long nativePtr);
private static native void setDnDActionsImpl(long nativePtr, int actions, int preferredAction);
private WLDataOffer(long nativePtr) {
if (nativePtr == 0) {
throw new IllegalArgumentException("nativePtr is null");
}
this.nativePtr = nativePtr;
}
// after calling destroy(), this object enters an invalid state and needs to be deleted
public void destroy() {
if (nativePtr != 0) {
destroyImpl(nativePtr);
nativePtr = 0;
}
}
public byte[] receiveData(String mime) throws IOException {
int fd;
if (nativePtr == 0) {
throw new IllegalStateException("nativePtr is 0");
}
fd = openReceivePipe(nativePtr, mime);
assert(fd != -1); // Otherwise an exception should be thrown from native code
FileDescriptor javaFD = new FileDescriptor();
jdk.internal.access.SharedSecrets.getJavaIOFileDescriptorAccess().set(javaFD, fd);
try (var in = new FileInputStream(javaFD)) {
return WLDataDevice.readAllBytesFrom(in);
}
}
public void accept(long serial, String mime) {
if (nativePtr == 0) {
throw new IllegalStateException("nativePtr is 0");
}
acceptImpl(nativePtr, serial, mime);
}
public void finishDnD() {
if (nativePtr == 0) {
throw new IllegalStateException("nativePtr is 0");
}
finishDnDImpl(nativePtr);
}
public void setDnDActions(int actions, int preferredAction) {
if (nativePtr == 0) {
throw new IllegalStateException("nativePtr is 0");
}
if (actions != 0) {
if ((actions & preferredAction) == 0) {
throw new IllegalArgumentException("preferredAction is not a valid action");
}
}
setDnDActionsImpl(nativePtr, actions, preferredAction);
}
public synchronized List<String> getMimes() {
return mimes;
}
// Event handlers, called from native code on the data device dispatch thread
private synchronized void handleOfferMime(String mime) {
mimes.add(mime);
}
private synchronized void handleSourceActions(int actions) {
sourceActions = actions;
}
private synchronized void handleAction(int action) {
selectedAction = action;
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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.awt.wl;
import java.awt.datatransfer.Transferable;
public class WLDataSource {
// nativePtr will be reset to 0 after this object receives a "cancelled" event, and is destroyed.
// Reading from nativePtr doesn't need to be synchronized for methods that happen before announcing
// this object as a selection, or a drag-and-drop source.
private long nativePtr;
private final Transferable data;
private native long initNative(long dataDeviceNativePtr, int protocol);
private static native void offerMimeImpl(long nativePtr, String mime);
private static native void destroyImpl(long nativePtr);
private static native void setDnDActionsImpl(long nativePtr, int actions);
WLDataSource(long dataDeviceNativePtr, int protocol, Transferable data) {
var wlDataTransferer = (WLDataTransferer) WLDataTransferer.getInstance();
nativePtr = initNative(dataDeviceNativePtr, protocol);
assert nativePtr != 0; // should've already thrown in native
this.data = data;
try {
if (data != null) {
long[] formats = wlDataTransferer.getFormatsForTransferableAsArray(data, wlDataTransferer.getFlavorTable());
for (long format : formats) {
String mime = wlDataTransferer.getNativeForFormat(format);
offerMimeImpl(nativePtr, mime);
}
}
} catch (Throwable e) {
destroyImpl(nativePtr);
throw e;
}
}
// Used by WLDataDevice to set this source as a selection or to start drag-and-drop.
// This method can only safely be called before setting this source as selection, or starting drag-and-drop,
// because after that, source might receive a cancel event at any time and be destroyed.
long getNativePtr() {
return nativePtr;
}
// This method can only be called once before setting this object as a drag-and-drop source
public void setDnDActions(int actions) {
if (nativePtr == 0) {
throw new IllegalStateException("Native pointer is null");
}
setDnDActionsImpl(nativePtr, actions);
}
public synchronized void destroy() {
if (nativePtr != 0) {
destroyImpl(nativePtr);
nativePtr = 0;
}
}
// Event handlers, called from native code on the data transferer dispatch thread
protected void handleSend(String mime, int fd) {
WLDataDevice.transferContentsWithType(data, mime, fd);
}
protected void handleCancelled() {
destroy();
}
protected void handleTargetAcceptsMime(String mime) {
// TODO: drag-and-drop implementation, synchronization
}
protected void handleDnDDropPerformed() {
// TODO: drag-and-drop implementation, synchronization
}
protected void handleDnDFinished() {
// TODO: drag-and-drop implementation, synchronization
}
protected void handleDnDAction(int action) {
// TODO: drag-and-drop implementation, synchronization
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2023 JetBrains s.r.o.
* Copyright 2025 JetBrains s.r.o.
* 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,6 +24,7 @@
*/
package sun.awt.wl;
import jdk.internal.misc.InnocuousThread;
import sun.awt.datatransfer.DataTransferer;
import sun.awt.datatransfer.ToolkitThreadBlockedHandler;
import sun.datatransfer.DataFlavorUtil;
@@ -39,6 +40,8 @@ import javax.imageio.stream.ImageInputStream;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.FlavorTable;
import java.awt.datatransfer.SystemFlavorMap;
import java.awt.datatransfer.Transferable;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
@@ -51,11 +54,13 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.Objects;
/**
@@ -66,8 +71,6 @@ import java.util.Objects;
* once established, this mapping never changes
*/
public class WLDataTransferer extends DataTransferer {
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.WLDataTransferer");
private static ImageTypeSpecifier defaultImageSpec = null;
// Maps the "native" format (MIME) to its numeric ID
@@ -79,6 +82,12 @@ public class WLDataTransferer extends DataTransferer {
private final Map<Long, Boolean> imageFormats = new HashMap<>();
private final Map<Long, Boolean> textFormats = new HashMap<>();
private final FlavorTable flavorTable;
public FlavorTable getFlavorTable() {
return flavorTable;
}
private static class HOLDER {
static WLDataTransferer instance = new WLDataTransferer();
}
@@ -87,6 +96,10 @@ public class WLDataTransferer extends DataTransferer {
return HOLDER.instance;
}
private WLDataTransferer() {
flavorTable = adaptFlavorMap(SystemFlavorMap.getDefaultFlavorMap());
}
@Override
public String getDefaultUnicodeEncoding() {
return "UTF-8";

View File

@@ -156,8 +156,7 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
private static boolean initialized = false;
private static Thread toolkitThread;
private final WLClipboard clipboard;
private final WLClipboard selection;
private final WLDataDevice dataDevice;
private static Cursor currentCursor;
@@ -191,17 +190,9 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
toolkitSystemThread.setDaemon(true);
toolkitSystemThread.start();
WLClipboard selectionClipboard = null;
try {
selectionClipboard = new WLClipboard("Selection", true);
} catch (UnsupportedOperationException ignored) {
}
clipboard = new WLClipboard("System", false);
selection = selectionClipboard;
dataDevice = new WLDataDevice(0); // TODO: for multiseat support pass wl_seat pointer here
} else {
clipboard = null;
selection = null;
dataDevice = null;
}
}
@@ -812,7 +803,7 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
security.checkPermission(AWTPermissions.ACCESS_CLIPBOARD_PERMISSION);
}
return clipboard;
return dataDevice.getSystemClipboard();
}
@Override
@@ -822,7 +813,7 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
if (security != null) {
security.checkPermission(AWTPermissions.ACCESS_CLIPBOARD_PERMISSION);
}
return selection;
return dataDevice.getPrimarySelectionClipboard();
}
@Override

View File

@@ -1,724 +0,0 @@
/*
* Copyright (c) 2023, JetBrains s.r.o.. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "JNIUtilities.h"
#include "sun_awt_wl_WLClipboard.h"
#include "wayland-client-protocol.h"
#include "WLToolkit.h"
// A type both zwp_primary_selection_source_v1* and wl_data_source*
// are convertible to.
typedef void* data_source_t;
static jmethodID transferContentsWithTypeMID; // WLCipboard.transferContentsWithType()
static jmethodID handleClipboardFormatMID; // WLCipboard.handleClipboardFormat()
static jmethodID handleNewClipboardMID; // WLCipboard.handleNewClipboard()
static jmethodID handleOfferCancelledMID; // WLCipboard.handleOfferCancelled()
static jfieldID isPrimaryFID; // WLClipboard.isPrimary
typedef struct DataSourcePayload {
data_source_t source;
jobject clipboard; // a global reference to WLClipboard
jobject content; // a global reference to Transferable
jboolean isPrimary;
} DataSourcePayload;
static DataSourcePayload *
DataSourcePayload_Create(jobject clipboard, jobject content)
{
DataSourcePayload * payload = malloc(sizeof(struct DataSourcePayload));
if (payload) {
payload->source = NULL;
payload->clipboard = clipboard;
payload->content = content;
}
return payload;
}
static void
DataSourcePayload_Destroy(DataSourcePayload* payload)
{
free(payload);
}
typedef struct DataOfferPayload {
jobject clipboard; // a global reference to WLClipboard
} DataOfferPayload;
static DataOfferPayload *
DataOfferPayload_Create(jobject clipboard)
{
// NB: this payload is associated with the clipboard and, once created,
// is never destroyed, much like the clipboard itself.
DataOfferPayload * payload = malloc(sizeof(struct DataOfferPayload));
if (payload) {
payload->clipboard = clipboard;
}
return payload;
}
// Clipboard "devices", one for the actual clipboard and one for the selection clipboard.
// Implicitly assumed that WLClipboard can only create once instance of each.
static struct wl_data_device *wl_data_device;
static struct zwp_primary_selection_device_v1 *zwp_selection_device;
static void data_device_handle_data_offer(
void *data,
struct wl_data_device *data_device,
struct wl_data_offer *offer);
static void data_device_handle_selection(
void *data,
struct wl_data_device *data_device,
struct wl_data_offer *offer);
static void
data_device_handle_enter(
void *data,
struct wl_data_device *wl_data_device,
uint32_t serial,
struct wl_surface *surface,
wl_fixed_t x,
wl_fixed_t y,
struct wl_data_offer *id)
{
// TODO
}
static void
data_device_handle_leave(void *data, struct wl_data_device *wl_data_device)
{
// TODO
}
static void
data_device_handle_motion(
void *data,
struct wl_data_device *wl_data_device,
uint32_t time,
wl_fixed_t x,
wl_fixed_t y)
{
// TODO
}
static void
data_device_handle_drop(void *data, struct wl_data_device *wl_data_device)
{
// TODO
}
static const struct wl_data_device_listener wl_data_device_listener = {
.data_offer = data_device_handle_data_offer,
.selection = data_device_handle_selection,
.enter = data_device_handle_enter,
.leave = data_device_handle_leave,
.motion = data_device_handle_motion,
.drop = data_device_handle_drop
};
static void
RegisterDataOfferWithMimeType(DataOfferPayload *payload, void *offer, const char *mime_type)
{
JNIEnv *env = getEnv();
jstring mimeTypeString = (*env)->NewStringUTF(env, mime_type);
EXCEPTION_CLEAR(env);
if (mimeTypeString) {
(*env)->CallVoidMethod(env, payload->clipboard, handleClipboardFormatMID, ptr_to_jlong(offer), mimeTypeString);
EXCEPTION_CLEAR(env);
(*env)->DeleteLocalRef(env, mimeTypeString);
}
}
static void
RegisterDataOffer(DataOfferPayload *payload, void *offer)
{
JNIEnv *env = getEnv();
(*env)->CallVoidMethod(env, payload->clipboard, handleNewClipboardMID, ptr_to_jlong(offer));
EXCEPTION_CLEAR(env);
}
static void
zwp_selection_offer(
void *data,
struct zwp_primary_selection_offer_v1 *offer,
const char *mime_type)
{
assert (data != NULL);
RegisterDataOfferWithMimeType(data, offer, mime_type);
}
const struct zwp_primary_selection_offer_v1_listener zwp_selection_offer_listener = {
.offer = zwp_selection_offer
};
static void
zwp_selection_device_handle_data_offer(
void *data,
struct zwp_primary_selection_device_v1 *device,
struct zwp_primary_selection_offer_v1 *offer)
{
zwp_primary_selection_offer_v1_add_listener(offer, &zwp_selection_offer_listener, data);
}
static void
zwp_selection_device_handle_selection(
void *data,
struct zwp_primary_selection_device_v1 *device,
struct zwp_primary_selection_offer_v1 *offer)
{
assert (data != NULL);
RegisterDataOffer(data, offer);
}
static const struct zwp_primary_selection_device_v1_listener zwp_selection_device_listener = {
.data_offer = zwp_selection_device_handle_data_offer,
.selection = zwp_selection_device_handle_selection
};
static void
wl_action(void *data, struct wl_data_offer *wl_data_offer, uint32_t dnd_action)
{
// TODO: this is for DnD
}
static void
wl_offer(void *data, struct wl_data_offer *offer, const char *mime_type)
{
assert (data != NULL);
RegisterDataOfferWithMimeType(data, offer, mime_type);
}
static void
wl_source_actions(void *data, struct wl_data_offer *wl_data_offer, uint32_t source_actions)
{
// TODO: this is for DnD
}
static const struct wl_data_offer_listener wl_data_offer_listener = {
.action = wl_action,
.offer = wl_offer,
.source_actions = wl_source_actions
};
static void
data_device_handle_data_offer(
void *data,
struct wl_data_device *data_device,
struct wl_data_offer *offer)
{
wl_data_offer_add_listener(offer, &wl_data_offer_listener, data);
}
static void data_device_handle_selection(
void *data,
struct wl_data_device *data_device,
struct wl_data_offer *offer)
{
assert (data != NULL);
RegisterDataOffer(data, offer);
}
static void
SendClipboardToFD(DataSourcePayload *payload, const char *mime_type, int fd)
{
JNIEnv *env = getEnv();
jstring mime_type_string = (*env)->NewStringUTF(env, mime_type);
EXCEPTION_CLEAR(env);
if (payload->clipboard != NULL && payload->content != NULL && mime_type_string != NULL && fd >= 0) {
(*env)->CallVoidMethod(env,
payload->clipboard,
transferContentsWithTypeMID,
payload->content,
mime_type_string,
fd);
EXCEPTION_CLEAR(env);
} else {
// The file is normally closed on the Java side, so only close here
// if the Java side wasn't involved.
close(fd);
}
if (mime_type_string != NULL) {
(*env)->DeleteLocalRef(env, mime_type_string);
}
}
static void
CleanupClipboard(DataSourcePayload *payload)
{
if (payload != NULL) {
JNIEnv* env = getEnv();
if (payload->clipboard != NULL) (*env)->DeleteGlobalRef(env, payload->clipboard);
if (payload->content != NULL) (*env)->DeleteGlobalRef(env, payload->content);
if (payload->source != NULL) {
if (payload->isPrimary) {
zwp_primary_selection_source_v1_destroy(payload->source);
} else {
wl_data_source_destroy(payload->source);
}
}
DataSourcePayload_Destroy(payload);
}
}
static void
OfferCancelled(DataSourcePayload *payload) {
JNIEnv *env = getEnv();
(*env)->CallVoidMethod(env, payload->clipboard, handleOfferCancelledMID, ptr_to_jlong(payload));
EXCEPTION_CLEAR(env);
CleanupClipboard(payload);
}
static void
wl_data_source_target(void *data,
struct wl_data_source *wl_data_source,
const char *mime_type)
{
// TODO
}
static void
wl_data_source_handle_send(
void *data,
struct wl_data_source *source,
const char *mime_type,
int fd)
{
assert(data);
SendClipboardToFD(data, mime_type, fd);
}
static void
wl_data_source_handle_cancelled(
void *data,
struct wl_data_source *source)
{
JNU_RUNTIME_ASSERT(getEnv(), data != NULL && source == ((DataSourcePayload*)data)->source, "Unexpected data source cancelled");
OfferCancelled(data);
}
static const struct wl_data_source_listener wl_data_source_listener = {
.target = wl_data_source_target,
.send = wl_data_source_handle_send,
.cancelled = wl_data_source_handle_cancelled
};
static void
zwp_selection_source_handle_send(
void *data,
struct zwp_primary_selection_source_v1 *source,
const char *mime_type,
int32_t fd)
{
DataSourcePayload * payload = data;
assert(payload);
SendClipboardToFD(payload, mime_type, fd);
}
static void
zwp_selection_source_handle_cancelled(
void *data,
struct zwp_primary_selection_source_v1 *source)
{
JNU_RUNTIME_ASSERT(getEnv(), data != NULL && source == ((DataSourcePayload*)data)->source, "Unexpected selection source cancelled");
OfferCancelled(data);
}
static const struct zwp_primary_selection_source_v1_listener zwp_selection_source_listener = {
.send = zwp_selection_source_handle_send,
.cancelled = zwp_selection_source_handle_cancelled
};
static jboolean
initJavaRefs(JNIEnv* env, jclass wlClipboardClass)
{
GET_METHOD_RETURN(transferContentsWithTypeMID,
wlClipboardClass,
"transferContentsWithType",
"(Ljava/awt/datatransfer/Transferable;Ljava/lang/String;I)V",
JNI_FALSE);
GET_METHOD_RETURN(handleClipboardFormatMID,
wlClipboardClass,
"handleClipboardFormat",
"(JLjava/lang/String;)V",
JNI_FALSE);
GET_METHOD_RETURN(handleNewClipboardMID,
wlClipboardClass,
"handleNewClipboard",
"(J)V",
JNI_FALSE);
GET_METHOD_RETURN(handleOfferCancelledMID,
wlClipboardClass,
"handleOfferCancelled",
"(J)V",
JNI_FALSE);
GET_FIELD_RETURN(isPrimaryFID,
wlClipboardClass,
"isPrimary",
"Z",
JNI_FALSE);
return JNI_TRUE;
}
/**
* Returns JNI_TRUE if the WLClipboard referred to by wlClipboard
* corresponds to the "primary selection" clipboard and JNI_FALSE
* otherwise.
* Depending on that, a different protocol must be used to communicate
* with Wayland (zwp_primary_selection_device_manager_v1 and
* wl_data_device_manager correspondingly).
*/
static jboolean
isPrimarySelectionClipboard(JNIEnv* env, jobject wlClipboard)
{
return (*env)->GetBooleanField(env, wlClipboard, isPrimaryFID);
}
/**
* Initializes data common to all clipboard objects. Called once in
* static initialization time of the WLClipboard class.
*
* Throws InternalError in case of any errors.
*/
JNIEXPORT void JNICALL
Java_sun_awt_wl_WLClipboard_initIDs(
JNIEnv *env,
jclass wlClipboardClass)
{
if (!initJavaRefs(env, wlClipboardClass)) {
JNU_ThrowInternalError(env, "Failed to find WLClipboard members");
}
}
JNIEXPORT jlong JNICALL
Java_sun_awt_wl_WLClipboard_createDataOfferQueue(
JNIEnv *env,
jclass wlClipboardClass)
{
struct wl_event_queue * queue = wl_display_create_queue(wl_display);
if (queue == NULL) {
JNU_ThrowInternalError(env, "Couldn't create an event queue for the clipboard");
}
return ptr_to_jlong(queue);
}
JNIEXPORT void JNICALL
Java_sun_awt_wl_WLClipboard_dispatchDataOfferQueueImpl(
JNIEnv *env,
jclass wlClipboardClass,
jlong dataOfferQueuePtr)
{
struct wl_event_queue * queue = jlong_to_ptr(dataOfferQueuePtr);
assert (queue != NULL);
while (wl_display_dispatch_queue(wl_display, queue) != -1) {
}
}
/**
* Initializes data for a specific clipboard object (the primary selection
* or the regular one). Called once per clipboard type.
*
* Returns the native handle to the corresponding clipboard.
*
* Throws UnsupportedOperationException in case of the primary selection
* clipboard is not available and isPrimary is true.
* Throws IllegalStateException in case of double-initialization.
*/
JNIEXPORT jlong JNICALL
Java_sun_awt_wl_WLClipboard_initNative(
JNIEnv *env,
jobject obj,
jboolean isPrimary)
{
if (!isPrimary) {
if (wl_data_device != NULL) {
JNU_ThrowByName(env, "java/lang/IllegalStateException", "one data device has already been created");
return 0;
}
} else {
if (zwp_selection_device != NULL) {
JNU_ThrowByName(env,
"java/lang/IllegalStateException",
"one primary selection device has already been created");
return 0;
}
}
jobject clipboardGlobalRef = (*env)->NewGlobalRef(env, obj); // normally never deleted
CHECK_NULL_RETURN(clipboardGlobalRef, 0);
DataOfferPayload *payload = DataOfferPayload_Create(clipboardGlobalRef);
if (payload == NULL) {
(*env)->DeleteGlobalRef(env, clipboardGlobalRef);
}
CHECK_NULL_THROW_OOME_RETURN(env, payload, "Failed to allocate memory for DataOfferPayload", 0);
if (!isPrimary) {
// TODO: may be needed by DnD also, initialize in a common place
wl_data_device = wl_data_device_manager_get_data_device(wl_ddm, wl_seat);
if (wl_data_device == NULL) {
(*env)->DeleteGlobalRef(env, clipboardGlobalRef);
JNU_ThrowByName(env,
"java/awt/AWTError",
"wl_data_device_manager_get_data_device() failed");
return 0;
}
wl_data_device_add_listener(wl_data_device, &wl_data_device_listener, payload);
} else {
if (zwp_selection_dm != NULL) {
zwp_selection_device = zwp_primary_selection_device_manager_v1_get_device(zwp_selection_dm, wl_seat);
if (zwp_selection_device == NULL) {
(*env)->DeleteGlobalRef(env, clipboardGlobalRef);
JNU_ThrowByName(env,
"java/awt/AWTError",
"zwp_primary_selection_device_manager_v1_get_device() failed");
return 0;
}
zwp_primary_selection_device_v1_add_listener(zwp_selection_device, &zwp_selection_device_listener, payload);
} else {
(*env)->DeleteGlobalRef(env, clipboardGlobalRef);
JNU_ThrowByName(env,
"java/lang/UnsupportedOperationException",
"zwp_primary_selection_device_manager_v1 not available");
}
}
return ptr_to_jlong(wl_data_device);
}
static jboolean
announceMimeTypesForSource(
JNIEnv * env,
jboolean isPrimary,
jobjectArray mimeTypes,
data_source_t source)
{
jint length = (*env)->GetArrayLength(env, mimeTypes);
for (jint i = 0; i < length; i++) {
jstring s = (*env)->GetObjectArrayElement(env, mimeTypes, i);
JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
const char *mimeType = (*env)->GetStringUTFChars(env, s, JNI_FALSE);
CHECK_NULL_RETURN(mimeType, JNI_FALSE);
if (isPrimary) {
zwp_primary_selection_source_v1_offer((struct zwp_primary_selection_source_v1 *)source, mimeType);
} else {
wl_data_source_offer((struct wl_data_source *)source, mimeType);
}
(*env)->ReleaseStringUTFChars(env, s, mimeType);
(*env)->DeleteLocalRef(env, s);
}
wlFlushToServer(env);
return JNI_TRUE;
}
static jboolean
offerData(
JNIEnv* env,
DataSourcePayload * payload,
jboolean isPrimary,
jlong eventSerial,
jobjectArray mimeTypes,
jlong dataOfferQueuePtr)
{
data_source_t source = isPrimary
? (data_source_t)zwp_primary_selection_device_manager_v1_create_source(zwp_selection_dm)
: (data_source_t)wl_data_device_manager_create_data_source(wl_ddm);
if (source != NULL) {
payload->source = source;
payload->isPrimary = isPrimary;
wl_proxy_set_queue((struct wl_proxy*)source, jlong_to_ptr(dataOfferQueuePtr));
if (isPrimary) {
zwp_primary_selection_source_v1_add_listener(
(struct zwp_primary_selection_source_v1 *)source,
&zwp_selection_source_listener,
payload);
} else {
wl_data_source_add_listener(
(struct wl_data_source *)source,
&wl_data_source_listener,
payload);
}
if (mimeTypes != NULL) {
if (!announceMimeTypesForSource(env, isPrimary, mimeTypes, source)) {
if (isPrimary) {
zwp_primary_selection_source_v1_destroy(source);
} else {
wl_data_source_destroy(source);
}
return JNI_FALSE;
}
}
if (isPrimary) {
zwp_primary_selection_device_v1_set_selection(
zwp_selection_device,
(struct zwp_primary_selection_source_v1 *)source,
eventSerial);
}
else {
wl_data_device_set_selection(
wl_data_device,
(struct wl_data_source *)source,
eventSerial);
}
wlFlushToServer(env);
}
return source != NULL;
}
/**
* Makes Wayland aware of the availability of new clipboard content in the
* given MIME formats.
* Retains the reference to clipboard content for the further use when the actual
* clipboard data get requested.
*/
JNIEXPORT jlong JNICALL
Java_sun_awt_wl_WLClipboard_offerData(
JNIEnv *env,
jobject obj,
jlong eventSerial,
jobjectArray mimeTypes,
jobject content,
jlong dataOfferQueuePtr)
{
jobject clipboardGlobalRef = (*env)->NewGlobalRef(env, obj); // deleted by ...source_handle_cancelled()
CHECK_NULL_RETURN(clipboardGlobalRef, 0);
jobject contentGlobalRef = (*env)->NewGlobalRef(env, content); // deleted by ...source_handle_cancelled()
CHECK_NULL_RETURN(contentGlobalRef, 0);
DataSourcePayload * payload = DataSourcePayload_Create(clipboardGlobalRef, contentGlobalRef);
if (payload == NULL) {
(*env)->DeleteGlobalRef(env, clipboardGlobalRef);
(*env)->DeleteGlobalRef(env, contentGlobalRef);
}
CHECK_NULL_THROW_OOME_RETURN(env, payload, "failed to allocate memory for DataSourcePayload", 0);
const jboolean isPrimary = isPrimarySelectionClipboard(env, obj);
if (!offerData(env, payload, isPrimary, eventSerial, mimeTypes, dataOfferQueuePtr)) {
// Failed to create a data source; give up and cleanup.
CleanupClipboard(payload);
}
return ptr_to_jlong(payload);
}
JNIEXPORT void JNICALL
Java_sun_awt_wl_WLClipboard_cancelOffer(
JNIEnv *env,
jobject obj,
jlong payloadNativePtr)
{
JNU_RUNTIME_ASSERT(env, payloadNativePtr != 0, "NULL pointer to clipboard data source");
CleanupClipboard(jlong_to_ptr(payloadNativePtr));
}
/**
* Asks Wayland to provide the data for the clipboard in the given MIME
* format.
*
* Returns the file descriptor from which the data must be read or -1
* in case of an error.
*
* NB: the returned file descriptor must be closed by the caller.
*/
JNIEXPORT jint JNICALL
Java_sun_awt_wl_WLClipboard_requestDataInFormat(
JNIEnv *env,
jobject obj,
jlong clipboardNativePtr,
jstring mimeTypeJava)
{
assert (clipboardNativePtr != 0);
const jboolean isPrimary = isPrimarySelectionClipboard(env, obj);
int fd = -1; // The file descriptor the clipboard data will be read from by Java
const char * mimeType = (*env)->GetStringUTFChars(env, mimeTypeJava, NULL);
if (mimeType) {
int fds[2];
int rc = pipe2(fds, O_CLOEXEC);
if (rc == 0) {
if (isPrimary) {
struct zwp_primary_selection_offer_v1 * offer = jlong_to_ptr(clipboardNativePtr);
zwp_primary_selection_offer_v1_receive(offer, mimeType, fds[1]);
} else {
struct wl_data_offer * offer = jlong_to_ptr(clipboardNativePtr);
wl_data_offer_receive(offer, mimeType, fds[1]);
}
// Since the request for the clipboard contents can and usually is blocking,
// make sure that the server has received it right away.
wlFlushToServer(env);
close(fds[1]); // close the "sender" end of the pipe
fd = fds[0];
}
(*env)->ReleaseStringUTFChars(env, mimeTypeJava, mimeType);
}
return fd;
}
/**
* Destroys the corresponding Wayland proxy objects pointed to by clipboardNativePtr.
*/
JNIEXPORT void JNICALL
Java_sun_awt_wl_WLClipboard_destroyClipboard(
JNIEnv *env,
jobject obj,
jlong clipboardNativePtr)
{
assert(clipboardNativePtr != 0);
if (isPrimarySelectionClipboard(env, obj)) {
struct zwp_primary_selection_offer_v1 * offer = jlong_to_ptr(clipboardNativePtr);
zwp_primary_selection_offer_v1_destroy(offer);
} else {
struct wl_data_offer * offer = jlong_to_ptr(clipboardNativePtr);
wl_data_offer_destroy(offer);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -45,7 +45,7 @@ final class FileInputStreamInstrumentor {
@JIInstrumentationMethod
public int read() throws IOException {
EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
if (!eventConfiguration.isEnabled() || ioOverNioInThisThread()) {
if (!eventConfiguration.isEnabled()) {
return read();
}
int result = 0;
@@ -72,7 +72,7 @@ final class FileInputStreamInstrumentor {
@JIInstrumentationMethod
public int read(byte b[]) throws IOException {
EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
if (!eventConfiguration.isEnabled() || ioOverNioInThisThread()) {
if (!eventConfiguration.isEnabled()) {
return read(b);
}
int bytesRead = 0;
@@ -96,7 +96,7 @@ final class FileInputStreamInstrumentor {
@JIInstrumentationMethod
public int read(byte b[], int off, int len) throws IOException {
EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
if (!eventConfiguration.isEnabled() || ioOverNioInThisThread()) {
if (!eventConfiguration.isEnabled()) {
return read(b, off, len);
}
int bytesRead = 0;
@@ -116,8 +116,4 @@ final class FileInputStreamInstrumentor {
}
return bytesRead;
}
private boolean ioOverNioInThisThread() {
throw new Error("This code should never be called. JFR should have replaced the call to this code with another method.");
}
}

View File

@@ -45,7 +45,7 @@ final class FileOutputStreamInstrumentor {
@JIInstrumentationMethod
public void write(int b) throws IOException {
EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
if (!eventConfiguration.isEnabled() || ioOverNioInThisThread()) {
if (!eventConfiguration.isEnabled()) {
write(b);
return;
}
@@ -66,7 +66,7 @@ final class FileOutputStreamInstrumentor {
@JIInstrumentationMethod
public void write(byte b[]) throws IOException {
EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
if (!eventConfiguration.isEnabled() || ioOverNioInThisThread()) {
if (!eventConfiguration.isEnabled()) {
write(b);
return;
}
@@ -87,7 +87,7 @@ final class FileOutputStreamInstrumentor {
@JIInstrumentationMethod
public void write(byte b[], int off, int len) throws IOException {
EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
if (!eventConfiguration.isEnabled() || ioOverNioInThisThread()) {
if (!eventConfiguration.isEnabled()) {
write(b, off, len);
return;
}
@@ -104,9 +104,4 @@ final class FileOutputStreamInstrumentor {
}
}
}
@SuppressWarnings("unused")
private boolean ioOverNioInThisThread() {
throw new Error("This code should never be called. JFR should have replaced the call to this code with another method.");
}
}

View File

@@ -46,7 +46,7 @@ final class RandomAccessFileInstrumentor {
@JIInstrumentationMethod
public int read() throws IOException {
EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
if (!eventConfiguration.isEnabled() || ioOverNioInThisThread()) {
if (!eventConfiguration.isEnabled()) {
return read();
}
int result = 0;
@@ -73,7 +73,7 @@ final class RandomAccessFileInstrumentor {
@JIInstrumentationMethod
public int read(byte b[]) throws IOException {
EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
if (!eventConfiguration.isEnabled() || ioOverNioInThisThread()) {
if (!eventConfiguration.isEnabled()) {
return read(b);
}
int bytesRead = 0;
@@ -97,7 +97,7 @@ final class RandomAccessFileInstrumentor {
@JIInstrumentationMethod
public int read(byte b[], int off, int len) throws IOException {
EventConfiguration eventConfiguration = EventConfigurations.FILE_READ;
if (!eventConfiguration.isEnabled() || ioOverNioInThisThread()) {
if (!eventConfiguration.isEnabled()) {
return read(b, off, len);
}
int bytesRead = 0;
@@ -121,7 +121,7 @@ final class RandomAccessFileInstrumentor {
@JIInstrumentationMethod
public void write(int b) throws IOException {
EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
if (!eventConfiguration.isEnabled() || ioOverNioInThisThread()) {
if (!eventConfiguration.isEnabled()) {
write(b);
return;
}
@@ -142,7 +142,7 @@ final class RandomAccessFileInstrumentor {
@JIInstrumentationMethod
public void write(byte b[]) throws IOException {
EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
if (!eventConfiguration.isEnabled() || ioOverNioInThisThread()) {
if (!eventConfiguration.isEnabled()) {
write(b);
return;
}
@@ -163,7 +163,7 @@ final class RandomAccessFileInstrumentor {
@JIInstrumentationMethod
public void write(byte b[], int off, int len) throws IOException {
EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE;
if (!eventConfiguration.isEnabled() || ioOverNioInThisThread()) {
if (!eventConfiguration.isEnabled()) {
write(b, off, len);
return;
}
@@ -180,8 +180,4 @@ final class RandomAccessFileInstrumentor {
}
}
}
private boolean ioOverNioInThisThread() {
throw new Error("This code should never be called. JFR should have replaced the call to this code with another method.");
}
}

View File

@@ -88,4 +88,7 @@ serviceability/sa/ClhsdbCDSCore.java initial_run,NOBUG generic-aarch64,macosx-al
vmTestbase/gc/gctests/LargeObjects/large002/TestDescription.java NOBUG linux-all timeout
vmTestbase/gc/gctests/StringInternSyncWithGC/StringInternSyncWithGC.java NOBUG macosx-all timeout on macstudio
vmTestbase/jit/escape/AdaptiveBlocking/AdaptiveBlocking001/AdaptiveBlocking001.java JBR-8798 linux-aarch64
vmTestbase/jit/misctests/JitBug1/JitBug1.java JBR-8801 linux-aarch64,windows-all
vmTestbase/jit/misctests/JitBug1/JitBug1.java JBR-8801 linux-aarch64,windows-all
vmTestbase/jit/misctests/Pi/Pi.java JBR-8854 linux-aarch64
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi002/TestDescription.java JBR-8546 windows-all
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi004/TestDescription.java JBR-8744 windows-all

View File

@@ -292,6 +292,9 @@ vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEa
#############################################################################
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi001/Multi001.java JBR-8545,JBR-8546 windows-all
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi002/TestDescription.java JBR-8545 windows-all
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi003/TestDescription.java 8076494 windows-x64
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java 8076494 windows-x64
vmTestbase/nsk/stress/thread/thread008.java initial_run windows-all

View File

@@ -65,33 +65,28 @@ public class BootClassPathMismatch {
test.testBootClassPathMismatchTwoJars();
}
/* Archive contains boot classes only, with Hello class on -Xbootclasspath/a path.
*
* Error should be detected if:
* dump time: -Xbootclasspath/a:${testdir}/hello.jar
* run-time : -Xbootclasspath/a:${testdir}/newdir/hello.jar
*
* or
* dump time: -Xbootclasspath/a:${testdir}/newdir/hello.jar
* run-time : -Xbootclasspath/a:${testdir}/hello.jar
*/
// Jars in bootclasspath were moved together, it should be ok
public void testBootClassPathMismatch() throws Exception {
String appJar = JarBuilder.getOrCreateHelloJar();
String appClasses[] = {"Hello"};
String jar2 = ClassFileInstaller.writeJar("jar2.jar", "pkg/C2");
String jars = appJar + File.pathSeparator + jar2;
String appClasses[] = {"Hello", "pkg/C2"};
String testDir = TestCommon.getTestDir("newdir");
String otherJar = testDir + File.separator + "hello.jar";
String otherJar2 = ClassFileInstaller.writeJar("newdir/jar2.jar", "pkg/C2");
String otherJars = otherJar + File.pathSeparator + otherJar2;
TestCommon.dump(appJar, appClasses, "-Xbootclasspath/a:" + appJar);
TestCommon.dump(appJar, appClasses, "-Xbootclasspath/a:" + jars);
TestCommon.run(
"-Xlog:cds",
"-cp", appJar, "-Xbootclasspath/a:" + otherJar, "Hello")
.assertAbnormalExit(mismatchMessage);
TestCommon.dump(appJar, appClasses, "-Xbootclasspath/a:" + otherJar);
"-Xlog:cds,class+path,cds+path",
"-cp", appJar, "-verbose:class",
"-Xbootclasspath/a:" + otherJars, "Hello")
.assertNormalExit("[class,load] Hello source: shared objects file");
TestCommon.run(
"-Xlog:cds",
"-cp", appJar, "-Xbootclasspath/a:" + appJar, "Hello")
.assertAbnormalExit(mismatchMessage);
"-Xlog:cds,class+path,cds+path",
"-cp", otherJar, "-verbose:class",
"-Xbootclasspath/a:" + otherJars, "Hello")
.assertNormalExit("[class,load] Hello source: shared objects file");
}
/* Archive contains boot classes only.

View File

@@ -0,0 +1,44 @@
/*
* @test
* @summary bootclasspath mismatch test.
* @requires vm.cds
* @library /test/lib
* @compile test-classes/CustomClassLoaderApp.java
* @run driver TestUnlinkedClassWithCDS
*/
import jdk.test.lib.helpers.ClassFileInstaller;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.cds.CDSTestUtils;
public class TestUnlinkedClassWithCDS {
public static void main(String[] args) throws Exception {
String libJar = ClassFileInstaller.writeJar("lib.jar", "Outer", "Outer$Inner");
String appJar = ClassFileInstaller.writeJar("app.jar", "CustomClassLoaderApp", "CustomClassLoader");
System.setProperty("test.noclasspath", "true");
TestCommon.startNewArchiveName();
String archive = TestCommon.getCurrentArchiveName();
run("dump",
"-cp", appJar,
"-XX:ArchiveClassesAtExit=" + archive,
"CustomClassLoaderApp",
libJar)
.shouldHaveExitValue(0)
.shouldContain("Declaring class: class Outer");
run("exec",
"-cp", appJar,
"-XX:SharedArchiveFile=" + archive,
"CustomClassLoaderApp",
libJar)
.shouldHaveExitValue(0)
.shouldContain("Declaring class: class Outer");
}
private static OutputAnalyzer run(String log, String... args) throws Exception {
ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(args);
return CDSTestUtils.executeAndLog(pb.start(), log);
}
}

View File

@@ -0,0 +1,45 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.Enumeration;
import java.io.IOException;
class CustomClassLoader {
public CustomClassLoader(String jarPath)
throws MalformedURLException, IOException {
URL[] urls = { new URL("jar:file:" + jarPath + "!/") };
jarFile = new JarFile(jarPath);
urlClassLoader = URLClassLoader.newInstance(urls);
}
private URLClassLoader urlClassLoader;
private JarFile jarFile;
public Class loadClass(String name) throws ClassNotFoundException {
Enumeration<JarEntry> e = jarFile.entries();
while (e.hasMoreElements()) {
JarEntry je = e.nextElement();
if (je.isDirectory() || !je.getName().endsWith(".class")){
continue;
}
String className = je.getName().substring(0, je.getName().length() - 6);
if (!className.equals(name)) {
continue;
}
className = className.replace('/', '.');
return urlClassLoader.loadClass(className);
}
throw new ClassNotFoundException(name);
}
}
public class CustomClassLoaderApp {
public static void main(String[] args) throws Exception {
CustomClassLoader classLoader = new CustomClassLoader(args[0]);
Class<?> c = classLoader.loadClass("Outer$Inner");
System.out.println("Declaring class: " + c.getDeclaringClass());
}
}

View File

@@ -1347,3 +1347,27 @@ jdk_swing_wayland= \
jdk_desktop_wayland = \
:jdk_awt_wayland \
:jdk_swing_wayland
# tests to be executed against Legacy Binary builds
jdk_awt_legacy_libc= \
:jdk_awt \
-jb/java/awt/wayland/VulkanMaskFillTest.java
jdk_swing_legacy_libc= \
:jdk_swing
jdk_desktop_legacy_libc = \
:jdk_desktop \
-jb/java/awt/wayland/VulkanMaskFillTest.java
# Wayland tests to be executed against Legacy Binary builds with -Dawt.toolkit.name=WLToolkit
jdk_awt_wayland_legacy_libc= \
:jdk_awt_wayland \
-jb/java/awt/wayland/VulkanMaskFillTest.java
jdk_swing_wayland_legacy_libc= \
:jdk_swing_wayland
jdk_desktop_wayland_legacy_libc = \
:jdk_awt_wayland_legacy_libc \
:jdk_swing_wayland_legacy_libc

View File

@@ -25,7 +25,7 @@
* @bug 8017212
* @summary Examine methods in File.java that access the file system do the
* right permission check when a security manager exists.
* @run main/othervm -Djava.security.manager=allow -Djbr.java.io.use.nio=false CheckPermission
* @run main/othervm -Djava.security.manager=allow CheckPermission
* @author Dan Xu
*/

View File

@@ -29,24 +29,24 @@
* @library /test/lib
*
* @summary Test: memory is properly limited using multiple buffers
* @run main/othervm -Djbr.java.io.use.nio=false -Djava.util.zip.use.nio.for.zip.file.access=false -XX:MaxDirectMemorySize=10 LimitDirectMemory true 10 1
* @run main/othervm -Djbr.java.io.use.nio=false -Djava.util.zip.use.nio.for.zip.file.access=false -XX:MaxDirectMemorySize=1k LimitDirectMemory true 1k 100
* @run main/othervm -Djbr.java.io.use.nio=false -Djava.util.zip.use.nio.for.zip.file.access=false -XX:MaxDirectMemorySize=10m LimitDirectMemory true 10m 10m
* @run main/othervm -Djava.util.zip.use.nio.for.zip.file.access=false -XX:MaxDirectMemorySize=10 LimitDirectMemory true 10 1
* @run main/othervm -Djava.util.zip.use.nio.for.zip.file.access=false -XX:MaxDirectMemorySize=1k LimitDirectMemory true 1k 100
* @run main/othervm -Djava.util.zip.use.nio.for.zip.file.access=false -XX:MaxDirectMemorySize=10m LimitDirectMemory true 10m 10m
*
* @summary Test: We can increase the amount of available memory
* @run main/othervm -Djbr.java.io.use.nio=false -Djava.util.zip.use.nio.for.zip.file.access=false -XX:MaxDirectMemorySize=65M LimitDirectMemory false 64M 65M
* @run main/othervm -Djava.util.zip.use.nio.for.zip.file.access=false -XX:MaxDirectMemorySize=65M LimitDirectMemory false 64M 65M
*
* @summary Test: Exactly the default amount of memory is available
* @run main/othervm LimitDirectMemory false 10 1
* @run main/othervm -Djbr.java.io.use.nio=false -Djava.util.zip.use.nio.for.zip.file.access=false -Xmx64m LimitDirectMemory false 0 DEFAULT
* @run main/othervm -Djbr.java.io.use.nio=false -Djava.util.zip.use.nio.for.zip.file.access=false -Xmx64m LimitDirectMemory true 0 DEFAULT+1
* @run main/othervm -Djava.util.zip.use.nio.for.zip.file.access=false -Xmx64m LimitDirectMemory false 0 DEFAULT
* @run main/othervm -Djava.util.zip.use.nio.for.zip.file.access=false -Xmx64m LimitDirectMemory true 0 DEFAULT+1
*
* @summary Test: We should be able to eliminate direct memory allocation entirely
* @run main/othervm -Djbr.java.io.use.nio=false -Djava.util.zip.use.nio.for.zip.file.access=false -XX:MaxDirectMemorySize=0 LimitDirectMemory true 0 1
* @run main/othervm -Djava.util.zip.use.nio.for.zip.file.access=false -XX:MaxDirectMemorySize=0 LimitDirectMemory true 0 1
*
* @summary Test: Setting the system property should not work so we should be able
* to allocate the default amount
* @run main/othervm -Djbr.java.io.use.nio=false -Djava.util.zip.use.nio.for.zip.file.access=false -Dsun.nio.MaxDirectMemorySize=1K -Xmx64m
* @run main/othervm -Djava.util.zip.use.nio.for.zip.file.access=false -Dsun.nio.MaxDirectMemorySize=1K -Xmx64m
* LimitDirectMemory false DEFAULT-1 DEFAULT/2
*/

View File

@@ -34,14 +34,12 @@ import java.io.File;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.AclEntry;
import java.nio.file.attribute.AclEntryPermission;
import java.nio.file.attribute.AclEntryType;
import java.nio.file.attribute.AclFileAttributeView;
import java.nio.file.attribute.DosFileAttributeView;
import java.nio.file.attribute.UserPrincipal;
import java.util.EnumSet;
import java.util.List;
import jdk.test.lib.Platform;
@@ -57,7 +55,6 @@ public class Misc {
testIsSameFile(dir);
testFileTypeMethods(dir);
testAccessMethods(dir);
testEmptyPathForByteStream();
} finally {
TestUtil.removeAll(dir);
}
@@ -363,18 +360,6 @@ public class Misc {
}
}
static void testEmptyPathForByteStream() throws IOException {
Path emptyPath = Path.of("");
try {
emptyPath.getFileSystem().provider()
.newByteChannel(emptyPath, EnumSet.of(StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW))
.close();
throw new RuntimeException("FileAlreadyExistsException was not thrown");
} catch (FileAlreadyExistsException ignored) {
// The expected behavior.
}
}
static void assertTrue(boolean okay) {
if (!okay)
throw new RuntimeException("Assertion Failed");

View File

@@ -45,14 +45,14 @@ import java.util.stream.Stream;
* @test
* @bug 8191033
* @build custom.DotHandler custom.Handler
* @run main/othervm -Djbr.java.io.use.nio=false -Dlogging.properties=badlogging.properties -Dclz=1custom.DotHandler BadRootLoggerHandlers CUSTOM
* @run main/othervm -Djbr.java.io.use.nio=false -Dlogging.properties=badlogging.properties -Dclz=1custom.DotHandler BadRootLoggerHandlers DEFAULT
* @run main/othervm -Djbr.java.io.use.nio=false -Dlogging.properties=badglobal.properties -Dclz=1custom.GlobalHandler BadRootLoggerHandlers CUSTOM
* @run main/othervm -Djbr.java.io.use.nio=false -Dlogging.properties=badglobal.properties -Dclz=1custom.GlobalHandler BadRootLoggerHandlers DEFAULT
* @run main/othervm/java.security.policy==test.policy -Djbr.java.io.use.nio=false -Dlogging.properties=badlogging.properties -Dclz=1custom.DotHandler BadRootLoggerHandlers CUSTOM
* @run main/othervm/java.security.policy==test.policy -Djbr.java.io.use.nio=false -Dlogging.properties=badlogging.properties -Dclz=1custom.DotHandler BadRootLoggerHandlers DEFAULT
* @run main/othervm/java.security.policy==test.policy -Djbr.java.io.use.nio=false -Dlogging.properties=badglobal.properties -Dclz=1custom.GlobalHandler BadRootLoggerHandlers CUSTOM
* @run main/othervm/java.security.policy==test.policy -Djbr.java.io.use.nio=false -Dlogging.properties=badglobal.properties -Dclz=1custom.GlobalHandler BadRootLoggerHandlers DEFAULT
* @run main/othervm -Dlogging.properties=badlogging.properties -Dclz=1custom.DotHandler BadRootLoggerHandlers CUSTOM
* @run main/othervm -Dlogging.properties=badlogging.properties -Dclz=1custom.DotHandler BadRootLoggerHandlers DEFAULT
* @run main/othervm -Dlogging.properties=badglobal.properties -Dclz=1custom.GlobalHandler BadRootLoggerHandlers CUSTOM
* @run main/othervm -Dlogging.properties=badglobal.properties -Dclz=1custom.GlobalHandler BadRootLoggerHandlers DEFAULT
* @run main/othervm/java.security.policy==test.policy -Dlogging.properties=badlogging.properties -Dclz=1custom.DotHandler BadRootLoggerHandlers CUSTOM
* @run main/othervm/java.security.policy==test.policy -Dlogging.properties=badlogging.properties -Dclz=1custom.DotHandler BadRootLoggerHandlers DEFAULT
* @run main/othervm/java.security.policy==test.policy -Dlogging.properties=badglobal.properties -Dclz=1custom.GlobalHandler BadRootLoggerHandlers CUSTOM
* @run main/othervm/java.security.policy==test.policy -Dlogging.properties=badglobal.properties -Dclz=1custom.GlobalHandler BadRootLoggerHandlers DEFAULT
* @author danielfuchs
*/
public class BadRootLoggerHandlers {

View File

@@ -10,8 +10,4 @@ grant {
permission java.lang.RuntimePermission "setIO";
permission java.lang.RuntimePermission "shutdownHooks";
permission java.lang.RuntimePermission "setContextClassLoader";
// JBR-7700
permission java.lang.RuntimePermission "accessUserInformation";
permission java.io.FilePermission "read";
};

View File

@@ -30,14 +30,18 @@ import java.io.InputStreamReader;
/**
* @test
* @summary VerifyDependencies checks readability verifies that a Linux shared
* library has no dependency on symbols from glibc version higher than 2.28
* library has no dependency on symbols from glibc version higher than <code>expectedVersion</code>
* @run main VerifyDependencies
* @requires (os.family == "linux")
*/
public class VerifyDependencies {
static final public String EXPECTED_VERSION = "2.28";
static final public String EXPECTED_VERSION_LEGACY = "2.17";
static final public String EXPECTED_VERSION_VULKAN = "2.28";
static String expectedVersion;
public static void verifyLibrary(String libraryPath) throws IOException {
Process process;
BufferedReader reader;
@@ -52,12 +56,12 @@ public class VerifyDependencies {
System.out.println(line);
if (line.contains("GLIBC_")) {
String version = extractVersion(line);
if (compareVersions(version, EXPECTED_VERSION) > 0) {
if (compareVersions(version, expectedVersion) > 0) {
throw new RuntimeException(libraryPath + " has a dependency on glibc version " + version);
}
}
}
System.out.println(libraryPath + " has no dependency on glibc version higher than " + EXPECTED_VERSION);
System.out.println(libraryPath + " has no dependency on glibc version higher than " + expectedVersion);
}
private static String extractVersion(String line) {
@@ -125,6 +129,12 @@ public class VerifyDependencies {
public static void main(String[] args) throws IOException {
String javaHome = System.getProperty("java.home");
String vendorVersion = System.getProperty("java.vendor.version");
expectedVersion = vendorVersion.substring(Math.max(vendorVersion.length() - 3, 0)).compareTo("-lb") == 0
? EXPECTED_VERSION_LEGACY : EXPECTED_VERSION_VULKAN;
System.out.println("supporting glibc version is not less than " + expectedVersion);
findInDirectory(javaHome + "/bin", false);
findInDirectory(javaHome + "/lib", true);
}

View File

@@ -1,282 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 java.io.File uses java.nio.file inside, special test for error messages consistency.
* @library testNio
* @run junit/othervm
* -Djava.nio.file.spi.DefaultFileSystemProvider=testNio.ManglingFileSystemProvider
* -Djbr.java.io.use.nio=true
* ErrorMessageTest
*/
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import testNio.ManglingFileSystemProvider;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.AccessDeniedException;
import java.nio.file.Files;
import java.util.Objects;
import static org.junit.Assert.fail;
@SuppressWarnings("ResultOfMethodCallIgnored")
public class ErrorMessageTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@BeforeClass
public static void checkSystemProperties() {
Objects.requireNonNull(System.getProperty("java.nio.file.spi.DefaultFileSystemProvider"));
}
@Before
@After
public void resetFs() {
ManglingFileSystemProvider.resetTricks();
}
public static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().startsWith("win");
public static final boolean IS_MAC = System.getProperty("os.name").toLowerCase().startsWith("mac");
@Test
public void noSuchFileOrDirectory() throws Exception {
File nonExistentEntity = temporaryFolder.newFile();
nonExistentEntity.delete();
File entityInNonExistentDir = new File(nonExistentEntity, "foo");
test(
new FileNotFoundException(nonExistentEntity + (IS_WINDOWS ? " (The system cannot find the file specified)" : " (No such file or directory)")),
() -> new FileInputStream(nonExistentEntity).close()
);
test(
new FileNotFoundException(nonExistentEntity + (IS_WINDOWS ? " (The system cannot find the file specified)" : " (No such file or directory)")),
() -> new RandomAccessFile(nonExistentEntity, "r").close()
);
test(
new IOException(IS_WINDOWS ? "The system cannot find the path specified" : "No such file or directory"),
entityInNonExistentDir::createNewFile
);
test(
new IOException(IS_WINDOWS ? "The system cannot find the path specified" : "No such file or directory"),
() -> File.createTempFile("foo", "bar", nonExistentEntity)
);
}
@Test
public void randomAccessFileWrongOperations() throws Exception {
File f = temporaryFolder.newFile();
try (RandomAccessFile readOnly = new RandomAccessFile(f, "r")) {
test(
new IOException("Bad file descriptor"),
() -> readOnly.write(1)
);
test(
new IOException("Bad file descriptor"),
() -> readOnly.write(new byte[1])
);
}
}
@Test
public void accessDenied() throws Exception {
File f;
if (IS_WINDOWS) {
f = new File("C:\\Windows\\System32\\config\\SAM");
try {
Files.list(f.toPath().getParent()).close();
Assume.assumeTrue(false);
} catch (AccessDeniedException ignored) {
// Nothing.
}
} else if (IS_MAC) {
Assume.assumeFalse(System.getProperty("user.name").equals("root"));
f = new File("/private/var/audit/current");
} else {
Assume.assumeFalse(System.getProperty("user.name").equals("root"));
f = new File("/etc/shadow");
}
test(
new FileNotFoundException(f + (IS_WINDOWS ? " (Access is denied)" : " (Permission denied)")),
() -> new FileInputStream(f).close()
);
test(
new FileNotFoundException(f + (IS_WINDOWS ? " (Access is denied)" : " (Permission denied)")),
() -> new FileOutputStream(f).close()
);
test(
new FileNotFoundException(f + (IS_WINDOWS ? " (Access is denied)" : " (Permission denied)")),
() -> new RandomAccessFile(f, "r").close()
);
if (IS_MAC) {
test(
new IOException("Permission denied"),
f::createNewFile
);
}
test(
new IOException(IS_WINDOWS ? "The system cannot find the path specified" : IS_MAC ? "Permission denied" : "Not a directory"),
() -> File.createTempFile("foo", "bar", f)
);
}
@Test
public void useDirectoryAsFile() throws Exception {
File dir = temporaryFolder.newFolder();
test(
new FileNotFoundException(dir + (IS_WINDOWS ? " (Access is denied)" : " (Is a directory)")),
() -> new FileInputStream(dir).close()
);
test(
new FileNotFoundException(dir + (IS_WINDOWS ? " (Access is denied)" : " (Is a directory)")),
() -> new FileOutputStream(dir).close()
);
test(
new FileNotFoundException(dir + (IS_WINDOWS ? " (Access is denied)" : " (Is a directory)")),
() -> new RandomAccessFile(dir, "r").close()
);
}
@Test
public void useFileAsDirectory() throws Exception {
File f = new File(temporaryFolder.newFile(), "foo");
test(
new FileNotFoundException(f + (IS_WINDOWS ? " (The system cannot find the path specified)" : " (Not a directory)")),
() -> new FileInputStream(f).close()
);
test(
new FileNotFoundException(f + (IS_WINDOWS ? " (The system cannot find the path specified)" : " (Not a directory)")),
() -> new FileOutputStream(f).close()
);
test(
new FileNotFoundException(f + (IS_WINDOWS ? " (The system cannot find the path specified)" : " (Not a directory)")),
() -> new RandomAccessFile(f, "r").close()
);
test(
new IOException((IS_WINDOWS ? "The system cannot find the path specified" : "Not a directory")),
f::createNewFile
);
test(
new IOException((IS_WINDOWS ? "The system cannot find the path specified" : "Not a directory")),
() -> File.createTempFile("foo", "bar", f)
);
}
@Test
public void symlinkLoop() throws Exception {
Assume.assumeFalse("This test doesn't support support symlinks on Windows", IS_WINDOWS);
File f = new File(temporaryFolder.newFolder(), "tricky_link");
Files.createSymbolicLink(f.toPath(), f.toPath());
test(
new FileNotFoundException(f + " (Too many levels of symbolic links)"),
() -> new FileInputStream(f).close()
);
test(
new FileNotFoundException(f + " (Too many levels of symbolic links)"),
() -> new FileOutputStream(f).close()
);
test(
new FileNotFoundException(f + " (Too many levels of symbolic links)"),
() -> new RandomAccessFile(f, "r").close()
);
test(
new IOException("Too many levels of symbolic links"),
() -> File.createTempFile("foo", "bar", f)
);
}
@Test
public void createNewFile() throws Exception {
test(
new IOException(IS_WINDOWS ? "The system cannot find the path specified" : "No such file or directory"),
() -> new File("").createNewFile()
);
}
// TODO Try to test operations of FileInputStream, FileOutputStream, etc.
private static void test(Exception expectedException, TestRunnable fn) {
test(expectedException, () -> {
fn.run();
return Void.TYPE;
});
}
private static <T> void test(Exception expectedException, TestComputable<T> fn) {
final T result;
try {
result = fn.run();
} catch (Exception err) {
if (err.getClass().equals(expectedException.getClass()) && Objects.equals(err.getMessage(), expectedException.getMessage())) {
return;
}
AssertionError assertionError = new AssertionError("Another exception was expected", err);
assertionError.addSuppressed(expectedException);
throw assertionError;
}
fail("Expected an exception but got a result: " + result);
}
@FunctionalInterface
private interface TestRunnable {
void run() throws Exception;
}
@FunctionalInterface
private interface TestComputable<T> {
T run() throws Exception;
}
}

View File

@@ -1,170 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 java.io.FileInputStream uses java.nio.file inside.
* @library testNio
* @run junit/othervm
* -Djava.nio.file.spi.DefaultFileSystemProvider=testNio.ManglingFileSystemProvider
* -Djbr.java.io.use.nio=true
* FileInputStreamTest
*/
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import testNio.ManglingFileSystemProvider;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Objects;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
public class FileInputStreamTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@BeforeClass
public static void checkSystemProperties() {
Objects.requireNonNull(System.getProperty("java.nio.file.spi.DefaultFileSystemProvider"));
}
@Before
@After
public void resetFs() {
ManglingFileSystemProvider.resetTricks();
}
@Test
public void readSingleByte() throws Exception {
File file = temporaryFolder.newFile();
Files.writeString(file.toPath(), "hello world");
ManglingFileSystemProvider.mangleFileContent = true;
try (FileInputStream fis = new FileInputStream(file)) {
StringBuilder sb = new StringBuilder();
while (true) {
int b = fis.read();
if (b == -1) {
break;
}
sb.append((char) b);
}
assertEquals("h3110 w0r1d", sb.toString());
}
}
@Test
public void readByteArray() throws Exception {
File file = temporaryFolder.newFile();
Files.writeString(file.toPath(), "hello world");
ManglingFileSystemProvider.mangleFileContent = true;
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buf = new byte[12345];
int read = fis.read(buf);
assertNotEquals(-1, read);
String content = new String(buf, 0, read, StandardCharsets.UTF_8);
assertEquals("h3110 w0r1d", content);
}
}
@Test
public void readAllBytes() throws Exception {
File file = temporaryFolder.newFile();
Files.writeString(file.toPath(), "hello world ");
ManglingFileSystemProvider.mangleFileContent = true;
ManglingFileSystemProvider.readExtraFileContent = true;
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buf = fis.readAllBytes();
String content = new String(buf, StandardCharsets.UTF_8);
assertEquals("h3110 w0r1d " + ManglingFileSystemProvider.extraContent, content);
}
}
@Test
public void transferTo() throws Exception {
File file = temporaryFolder.newFile();
Files.writeString(file.toPath(), "hello world");
ManglingFileSystemProvider.mangleFileContent = true;
try (FileInputStream fis = new FileInputStream(file)) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
fis.transferTo(baos);
assertEquals("h3110 w0r1d", baos.toString(StandardCharsets.UTF_8));
}
}
}
@Test
public void skip() throws Exception {
File file = temporaryFolder.newFile();
Files.writeString(file.toPath(), "especially lovely greet");
ManglingFileSystemProvider.mangleFileContent = true;
StringBuilder sb = new StringBuilder();
try (FileInputStream fis = new FileInputStream(file)) {
sb.append((char) fis.read());
assertEquals(10, fis.skip(10));
sb.append((char) fis.read());
assertEquals(8, fis.skip(8));
sb.append(new String(fis.readAllBytes(), StandardCharsets.UTF_8));
}
assertEquals("31337", sb.toString());
}
@Test
public void available() throws Exception {
File file = temporaryFolder.newFile();
try (FileInputStream fis = new FileInputStream(file)) {
assertEquals(0, fis.available());
}
ManglingFileSystemProvider.readExtraFileContent = true;
try (FileInputStream fis = new FileInputStream(file)) {
assertEquals(ManglingFileSystemProvider.extraContent.length(), fis.available());
byte[] bytes = fis.readAllBytes();
assertEquals(ManglingFileSystemProvider.extraContent, new String(bytes, StandardCharsets.UTF_8));
}
}
@Test
public void getChannel() throws Exception {
File file = temporaryFolder.newFile();
try (FileInputStream fis = new FileInputStream(file)) {
FileChannel channel = fis.getChannel();
assertTrue(channel.getClass().getName(), channel instanceof testNio.ManglingFileChannel);
}
}
}

View File

@@ -1,103 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 java.io.FileOutputStream uses java.nio.file inside.
* @library testNio
* @run junit/othervm
* -Djava.nio.file.spi.DefaultFileSystemProvider=testNio.ManglingFileSystemProvider
* -Djbr.java.io.use.nio=true
* FileOutputStreamTest
*/
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import testNio.ManglingFileSystemProvider;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.util.Objects;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class FileOutputStreamTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@BeforeClass
public static void checkSystemProperties() {
Objects.requireNonNull(System.getProperty("java.nio.file.spi.DefaultFileSystemProvider"));
}
@Before
@After
public void resetFs() {
ManglingFileSystemProvider.resetTricks();
}
@Test
public void writeSingleByte() throws Exception {
File file = temporaryFolder.newFile();
ManglingFileSystemProvider.mangleFileContent = true;
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write('l');
fos.write('e');
fos.write('e');
fos.write('t');
}
ManglingFileSystemProvider.mangleFileContent = false;
assertEquals("1337", Files.readString(file.toPath()));
}
@Test
public void writeByteArray() throws Exception {
File file = temporaryFolder.newFile();
ManglingFileSystemProvider.mangleFileContent = true;
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write("hello".getBytes());
}
ManglingFileSystemProvider.mangleFileContent = false;
assertEquals("h3110", Files.readString(file.toPath()));
}
@Test
public void getChannel() throws Exception {
File file = temporaryFolder.newFile();
try (FileOutputStream fos = new FileOutputStream(file)) {
FileChannel channel = fos.getChannel();
assertTrue(channel.getClass().getName(), channel instanceof testNio.ManglingFileChannel);
}
}
}

View File

@@ -1,599 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 java.io.File uses java.nio.file inside.
* @library testNio
* @run junit/othervm
* -Djava.nio.file.spi.DefaultFileSystemProvider=testNio.ManglingFileSystemProvider
* -Djbr.java.io.use.nio=true
* FileTest
*/
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import testNio.ManglingFileSystemProvider;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.nio.file.AccessDeniedException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Objects;
import static java.util.Arrays.sort;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class FileTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@BeforeClass
public static void checkSystemProperties() {
Objects.requireNonNull(System.getProperty("java.nio.file.spi.DefaultFileSystemProvider"));
}
public static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().startsWith("win");
private static void assumeNotWindows() {
Assume.assumeFalse(IS_WINDOWS);
}
@Before
@After
public void resetFs() throws Exception {
ManglingFileSystemProvider.resetTricks();
try (var dirStream = Files.walk(temporaryFolder.getRoot().toPath())) {
dirStream.sorted(Comparator.reverseOrder()).forEach(path -> {
if (!path.equals(temporaryFolder.getRoot().toPath())) {
try {
if (IS_WINDOWS) {
Files.setAttribute(path, "dos:readonly", false);
}
Files.delete(path);
} catch (IOException err) {
throw new UncheckedIOException(err);
}
}
});
}
}
@Test
public void getAbsolutePath() throws Exception {
File file = temporaryFolder.newFile("hello world");
assertNotEquals(file.getAbsolutePath(), ManglingFileSystemProvider.mangle(file.getAbsolutePath()));
ManglingFileSystemProvider.manglePaths = true;
assertEquals(file.getAbsolutePath(), ManglingFileSystemProvider.mangle(file.getAbsolutePath()));
}
@Test
public void canRead() throws Exception {
File file = temporaryFolder.newFile("testFile.txt");
assertTrue(file.canRead());
ManglingFileSystemProvider.denyAccessToEverything = true;
assertFalse(file.canRead());
}
@Test
public void canWrite() throws Exception {
assumeNotWindows();
File file = temporaryFolder.newFile("testFile.txt");
assertTrue(file.canWrite());
ManglingFileSystemProvider.denyAccessToEverything = true;
assertFalse(file.canWrite());
}
@Test
public void handlingEmptyPath() throws Exception {
File file = new File("");
// These checks fail
assertFalse(file.exists());
assertFalse(file.isDirectory());
assertFalse(file.isFile());
assertFalse(file.canRead());
if (IS_WINDOWS) {
assertTrue(file.setReadable(true));
} else {
assertFalse(file.setReadable(true));
}
assertFalse(file.canRead());
assertFalse(file.canWrite());
assertFalse(file.setWritable(true));
assertFalse(file.canWrite());
assertFalse(file.canExecute());
if (IS_WINDOWS) {
assertTrue(file.setExecutable(true));
} else {
assertFalse(file.setExecutable(true));
}
assertFalse(file.canExecute());
assertFalse(file.setLastModified(1234567890L));
assertEquals(null, file.list());
if (IS_WINDOWS) {
assertFalse(file.setReadOnly());
}
}
@Test
public void isDirectory() throws Exception {
File dir = temporaryFolder.newFolder("testDir");
File file = new File(dir, "testFile.txt");
assertTrue(file.createNewFile());
assertTrue(dir.isDirectory());
assertFalse(file.isDirectory());
ManglingFileSystemProvider.allFilesAreEmptyDirectories = true;
assertTrue(dir.isDirectory());
assertTrue(file.isDirectory());
}
@Test
public void exists() throws Exception {
File file = temporaryFolder.newFile("testFile.txt");
File dir = temporaryFolder.newFolder("testDir");
assertTrue(file.exists());
assertTrue(dir.exists());
assertFalse(new File(dir, "non-existing-file").exists());
assertFalse(new File(file, "non-existing-file").exists());
// Corner cases
assertFalse(new File("").exists());
assertTrue(new File(".").exists());
assertTrue(new File("..").exists());
if (IS_WINDOWS) {
assertTrue(new File("C:\\..\\..").exists());
} else {
assertTrue(new File("/../..").exists());
}
boolean parentOfDirThatDoesNotExist = new File("dir-that-does-not-exist/..").exists();
if (IS_WINDOWS) {
assertTrue(parentOfDirThatDoesNotExist);
} else {
assertFalse(parentOfDirThatDoesNotExist);
}
}
@Test
public void isFile() throws Exception {
File file = temporaryFolder.newFile("testFile.txt");
File dir = temporaryFolder.newFolder("testDir");
assertTrue(file.isFile());
assertFalse(dir.isFile());
ManglingFileSystemProvider.allFilesAreEmptyDirectories = true;
assertFalse(file.isFile());
assertFalse(dir.isFile());
}
@Test
public void delete() throws Exception {
File file1 = temporaryFolder.newFile("file1.txt");
File file2 = temporaryFolder.newFile("file2.txt");
assertTrue(file1.exists());
assertTrue(file2.exists());
assertTrue(file1.delete());
assertFalse(file1.exists());
ManglingFileSystemProvider.prohibitFileTreeModifications = true;
assertFalse(file2.delete());
assertTrue(file2.exists());
}
@Test
public void list() throws Exception {
File dir = temporaryFolder.newFolder("testDir");
File file1 = new File(dir, "file1.txt");
File file2 = new File(dir, "file2.txt");
assertTrue(file1.createNewFile());
assertTrue(file2.createNewFile());
String[] files = dir.list();
sort(files);
assertArrayEquals(new String[]{"file1.txt", "file2.txt"}, files);
ManglingFileSystemProvider.manglePaths = true;
ManglingFileSystemProvider.addEliteToEveryDirectoryListing = true;
files = dir.list();
sort(files);
assertArrayEquals(new String[]{"37337", "f1131.7x7", "f1132.7x7"}, files);
}
@Test
public void mkdir() throws Exception {
File dir1 = new File(temporaryFolder.getRoot(), "newDir1");
assertTrue(dir1.mkdir());
assertTrue(dir1.isDirectory());
ManglingFileSystemProvider.prohibitFileTreeModifications = true;
File dir2 = new File(temporaryFolder.getRoot(), "newDir2");
assertFalse(dir2.mkdir());
assertFalse(dir2.exists());
}
@Test
public void renameTo() throws Exception {
File file = temporaryFolder.newFile("originalName.txt");
File renamedFile = new File(temporaryFolder.getRoot(), "newName.txt");
assertTrue(file.exists());
assertFalse(renamedFile.exists());
ManglingFileSystemProvider.prohibitFileTreeModifications = true;
File renamedFile2 = new File(temporaryFolder.getRoot(), "newName2.txt");
assertFalse(renamedFile2.renameTo(renamedFile));
assertFalse(renamedFile2.exists());
}
@Test
public void setLastModified() throws Exception {
File file = temporaryFolder.newFile("testFile.txt");
// Beware that getting and setting mtime/atime/ctime is often unreliable.
Assume.assumeTrue(file.setLastModified(1234567890L));
ManglingFileSystemProvider.prohibitFileTreeModifications = true;
assertFalse(file.setLastModified(123459999L));
}
@Test
public void setReadOnly() throws Exception {
File file1 = temporaryFolder.newFile("testFile1.txt");
assertTrue(file1.canWrite());
assertTrue(file1.setReadOnly());
assertFalse(file1.canWrite());
ManglingFileSystemProvider.prohibitFileTreeModifications = true;
File file2 = temporaryFolder.newFile("testFile2.txt");
assertFalse(file2.setReadOnly());
assertTrue(file2.canWrite());
}
@Test
public void setWritable() throws Exception {
assumeNotWindows();
assertTrue(temporaryFolder.newFile("testFile1.txt").setWritable(false));
File file2 = temporaryFolder.newFile("testFile2.txt");
ManglingFileSystemProvider.prohibitFileTreeModifications = true;
assertFalse(file2.setWritable(false));
}
@Test
public void setReadable() throws Exception {
Assume.assumeFalse("setReadable(false) doesn't work for some reason on Windows, even for original java.io.File", IS_WINDOWS);
File file1 = temporaryFolder.newFile("testFile1.txt");
assertTrue(file1.setReadable(false));
assertFalse(file1.canRead());
File file2 = temporaryFolder.newFile("testFile2.txt");
ManglingFileSystemProvider.prohibitFileTreeModifications = true;
assertFalse(file2.setReadable(false));
assertTrue(file2.canRead());
}
@Test
public void setExecutable() throws Exception {
assumeNotWindows();
File file1 = temporaryFolder.newFile("testFile1.txt");
Assume.assumeFalse(file1.canExecute());
assertTrue(file1.setExecutable(true));
assertTrue(file1.canExecute());
File file2 = temporaryFolder.newFile("testFile2.txt");
ManglingFileSystemProvider.prohibitFileTreeModifications = true;
assertFalse(file2.setExecutable(true));
assertFalse(file2.canExecute());
}
@Test
public void listRoots() throws Exception {
File[] roots1 = File.listRoots();
String rootsString1 = Arrays.toString(roots1);
assertFalse(rootsString1, rootsString1.contains("31337"));
ManglingFileSystemProvider.addEliteToEveryDirectoryListing = true;
File[] roots2 = File.listRoots();
String rootsString2 = Arrays.toString(roots2);
assertTrue(rootsString2, rootsString2.contains("31337"));
}
@Test
public void getCanonicalPath() throws Exception {
assumeNotWindows();
// On macOS, the default temporary directory is a symlink.
// The test won't work correctly without canonicalization here.
File dir = temporaryFolder.newFolder().getCanonicalFile();
File file = new File(dir, "file");
Files.createFile(file.toPath());
Files.createSymbolicLink(file.toPath().resolveSibling("123"), file.toPath());
ManglingFileSystemProvider.manglePaths = true;
ManglingFileSystemProvider.mangleOnlyFileName = true;
assertEquals(new File(dir, "f113").toString(), new File(dir, "123").getCanonicalPath());
}
@Test
public void normalizationInConstructor() throws Exception {
assertEquals(".", new File(".").toString());
}
@Test
public void unixSocketExists() throws Exception {
assumeNotWindows();
// Can't use `temporaryFolder` because it may have a long path,
// but the length of a Unix socket path is limited in the Kernel.
String shortTmpDir;
{
Process process = new ProcessBuilder("mktemp", "-d")
.redirectInput(ProcessBuilder.Redirect.PIPE)
.start();
try (BufferedReader br = new BufferedReader(process.inputReader())) {
shortTmpDir = br.readLine();
}
assertEquals(0, process.waitFor());
}
try {
File unixSocket = new File(shortTmpDir, "unix-socket");
Process ncProcess = new ProcessBuilder("nc", "-lU", unixSocket.toString())
.redirectError(ProcessBuilder.Redirect.INHERIT)
.start();
assertEquals(0, new ProcessBuilder(
"sh", "-c",
"I=50; while [ $I -gt 0 && test -S " + unixSocket + " ]; do sleep 0.1; I=$(expr $I - 1); done; test -S " + unixSocket)
.start()
.waitFor());
try {
assertTrue(unixSocket.exists());
} finally {
ncProcess.destroy();
}
} finally {
new ProcessBuilder("rm", "-rf", shortTmpDir).start();
}
}
@Test
public void mkdirsWithDot() throws Exception {
File dir = new File(temporaryFolder.getRoot(), "newDir1/.");
assertTrue(dir.mkdirs());
assertTrue(dir.isDirectory());
}
@Test
public void canonicalizeTraverseBeyondRoot() throws Exception {
File root = temporaryFolder.getRoot().toPath().getFileSystem().getRootDirectories().iterator().next().toFile();
assertEquals(root, new File(root, "..").getCanonicalFile());
assertEquals(new File(root, "123"), new File(root, "../123").getCanonicalFile());
}
@Test
public void canonicalizeRelativePath() throws Exception {
File cwd = new File(System.getProperty("user.dir")).getAbsoluteFile();
assertEquals(cwd, new File("").getCanonicalFile());
assertEquals(cwd, new File(".").getCanonicalFile());
assertEquals(new File(cwd, "..").toPath().normalize().toFile(), new File("..").getCanonicalFile());
assertEquals(new File(cwd, "abc"), new File("abc").getCanonicalFile());
assertEquals(new File(cwd, "abc"), new File("abc/.").getCanonicalFile());
assertEquals(cwd, new File("abc/..").getCanonicalFile());
}
@Test
public void renameFileToAlreadyExistingFile() throws Exception {
File file1 = temporaryFolder.newFile("testFile1.txt");
try (var fos = new FileOutputStream(file1)) {
fos.write("file1".getBytes());
}
File file2 = temporaryFolder.newFile("testFile2.txt");
try (var fos = new FileOutputStream(file2)) {
fos.write("file2".getBytes());
}
assertTrue(file1.exists());
assertTrue(file2.exists());
assertTrue(file1.renameTo(file2));
assertFalse(file1.exists());
assertTrue(file2.exists());
try (var fis = Files.newInputStream(file2.toPath());
var bis = new BufferedReader(new InputStreamReader(fis))) {
String line = bis.readLine();
assertEquals("file1", line);
}
}
@Test
public void testToCanonicalPathSymLinksAware() throws Exception {
// getCanonicalFile capitalizes the drive letter on Windows.
File rootDir = temporaryFolder.newFolder("root").getCanonicalFile();
temporaryFolder.newFolder("root/dir1/dir2/dir3/dir4");
String root = rootDir.getAbsolutePath();
// non-recursive link
Path link1 = new File(rootDir, "dir1/dir2_link").toPath();
Path target1 = new File(rootDir, "dir1/dir2").toPath();
try {
Files.createSymbolicLink(link1, target1);
} catch (AccessDeniedException ignored) {
Assume.assumeTrue("Cannot create symbolic link", false);
}
// recursive links to a parent dir
Path link = new File(rootDir, "dir1/dir1_link").toPath();
Path target = new File(rootDir, "dir1").toPath();
Files.createSymbolicLink(link, target);
// links should NOT be resolved when ../ stays inside the linked path
assertEqualsReplacingSeparators(root + "/dir1/dir2", canonicalize(root + "/dir1/dir2_link/./"));
assertEqualsReplacingSeparators(root + "/dir1/dir2", canonicalize(root + "/dir1/dir2_link/dir3/../"));
assertEqualsReplacingSeparators(root + "/dir1/dir2/dir3", canonicalize(root + "/dir1/dir2_link/dir3/dir4/../"));
assertEqualsReplacingSeparators(root + "/dir1/dir2", canonicalize(root + "/dir1/dir2_link/dir3/dir4/../../"));
assertEqualsReplacingSeparators(root + "/dir1/dir2", canonicalize(root + "/dir1/../dir1/dir2_link/dir3/../"));
// I.II) recursive links
assertEqualsReplacingSeparators(root + "/dir1", canonicalize(root + "/dir1/dir1_link/./"));
assertEqualsReplacingSeparators(root + "/dir1", canonicalize(root + "/dir1/dir1_link/dir2/../"));
assertEqualsReplacingSeparators(root + "/dir1/dir2", canonicalize(root + "/dir1/dir1_link/dir2/dir3/../"));
assertEqualsReplacingSeparators(root + "/dir1", canonicalize(root + "/dir1/dir1_link/dir2/dir3/../../"));
assertEqualsReplacingSeparators(root + "/dir1", canonicalize(root + "/dir1/../dir1/dir1_link/dir2/../"));
// II) links should be resolved is ../ escapes outside
// II.I) non-recursive links
assertEqualsReplacingSeparators(root + "/dir1", canonicalize(root + "/dir1/dir2_link/../"));
assertEqualsReplacingSeparators(root + "/dir1/dir2", canonicalize(root + "/dir1/dir2_link/../dir2"));
assertEqualsReplacingSeparators(root + "/dir1/dir2", canonicalize(root + "/dir1/dir2_link/../../dir1/dir2"));
assertEqualsReplacingSeparators(root + "/dir1/dir2", canonicalize(root + "/dir1/dir2_link/dir3/../../dir2"));
assertEqualsReplacingSeparators(root + "/dir1/dir2", canonicalize(root + "/dir1/dir2_link/dir3/../../../dir1/dir2"));
assertEqualsReplacingSeparators(root + "/dir1/dir2", canonicalize(root + "/dir1/../dir1/dir2_link/../dir2"));
if (IS_WINDOWS) {
assertEqualsReplacingSeparators(root + "/dir1", canonicalize(root + "/dir1/dir1_link/../"));
assertEqualsReplacingSeparators(root + "/dir1/dir1", canonicalize(root + "/dir1/dir1_link/../dir1"));
assertEqualsReplacingSeparators(root + "/root/dir1", canonicalize(root + "/dir1/dir1_link/../../root/dir1"));
assertEqualsReplacingSeparators(root + "/dir1/dir1", canonicalize(root + "/dir1/dir1_link/dir2/../../dir1"));
assertEqualsReplacingSeparators(root + "/root/dir1", canonicalize(root + "/dir1/dir1_link/dir2/../../../root/dir1"));
assertEqualsReplacingSeparators(root + "/dir1/dir1", canonicalize(root + "/dir1/../dir1/dir1_link/../dir1"));
} else {
assertEqualsReplacingSeparators(root, canonicalize(root + "/dir1/dir1_link/../"));
assertEqualsReplacingSeparators(root + "/dir1", canonicalize(root + "/dir1/dir1_link/../dir1"));
assertEqualsReplacingSeparators(root + "/dir1", canonicalize(root + "/dir1/dir1_link/../../root/dir1"));
assertEqualsReplacingSeparators(root + "/dir1", canonicalize(root + "/dir1/dir1_link/dir2/../../dir1"));
assertEqualsReplacingSeparators(root + "/dir1", canonicalize(root + "/dir1/dir1_link/dir2/../../../root/dir1"));
assertEqualsReplacingSeparators(root + "/dir1", canonicalize(root + "/dir1/../dir1/dir1_link/../dir1"));
}
}
private static String canonicalize(String path) throws IOException {
return new File(path).getCanonicalFile().toString();
}
private static void assertEqualsReplacingSeparators(String expected, String actual) {
assertEquals(expected.replace('\\', '/'), actual.replace('\\', '/'));
}
@Test
public void testCreateNewFile() throws Exception {
File rootDir = temporaryFolder.newFolder();
File f = new File(rootDir, "hello.txt");
assertFalse(f.exists());
assertTrue(f.createNewFile());
assertTrue(f.exists());
assertFalse(f.createNewFile());
assertTrue(f.exists());
// Corner cases.
assertFalse(rootDir.createNewFile());
try {
boolean ignored = new File("").createNewFile();
fail("Expected IOException");
} catch (IOException e) {
// Nothing.
}
assertFalse(new File(".").createNewFile());
assertFalse(new File("..").createNewFile());
}
@Test
public void testDeletionOfReadOnlyFileOnWindows() throws Exception {
Assume.assumeTrue(IS_WINDOWS);
File dir = temporaryFolder.newFolder();
File file = new File(dir, "testFile.txt");
assertTrue(file.createNewFile());
assertTrue(file.setReadOnly());
assertTrue(file.delete());
assertFalse(file.exists());
}
// TODO Test file size.
// @Test
// public void getTotalSpace() throws Exception {
// throw new UnsupportedOperationException();
// }
//
// @Test
// public void getFreeSpace() throws Exception {
// throw new UnsupportedOperationException();
// }
//
// @Test
// public void getUsableSpace() throws Exception {
// throw new UnsupportedOperationException();
// }
//
// @Test
// public void compareTo() throws Exception {
// throw new UnsupportedOperationException();
// }
}

View File

@@ -1,271 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 java.io.RandomAccessFileTest uses java.nio.file inside.
* @library testNio
* @run junit/othervm
* -Djava.nio.file.spi.DefaultFileSystemProvider=testNio.ManglingFileSystemProvider
* -Djbr.java.io.use.nio=true
* RandomAccessFileTest
*/
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import testNio.ManglingFileSystemProvider;
import java.io.EOFException;
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Objects;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class RandomAccessFileTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
@BeforeClass
public static void checkSystemProperties() {
Objects.requireNonNull(System.getProperty("java.nio.file.spi.DefaultFileSystemProvider"));
}
private static void assumeNotWindows() {
Assume.assumeFalse(System.getProperty("os.name").toLowerCase().startsWith("win"));
}
@Before
@After
public void resetFs() {
ManglingFileSystemProvider.resetTricks();
}
@Test
public void usesNioForNonExistingFiles() throws Exception {
File nonExistingFile = new File(temporaryFolder.getRoot(), "non-existing-file");
assertFalse(Files.exists(nonExistingFile.toPath()));
ManglingFileSystemProvider.mangleFileContent = true;
try (RandomAccessFile rac = new RandomAccessFile(nonExistingFile, "rw")) {
byte[] buffer = "hello".getBytes();
rac.write(buffer);
rac.seek(0);
rac.readFully(buffer);
assertEquals("h3110", new String(buffer));
}
}
@Test
public void getChannel() throws Exception {
File file = temporaryFolder.newFile();
try (RandomAccessFile rac = new RandomAccessFile(file, "r")) {
FileChannel channel = rac.getChannel();
assertTrue(channel.getClass().getName(), channel instanceof testNio.ManglingFileChannel);
}
try (RandomAccessFile rac = new RandomAccessFile(file, "rw")) {
FileChannel channel = rac.getChannel();
assertTrue(channel.getClass().getName(), channel instanceof testNio.ManglingFileChannel);
}
}
@Test
public void getFilePointer() throws Exception {
File file = temporaryFolder.newFile();
try (RandomAccessFile rac = new RandomAccessFile(file, "r")) {
assertEquals(0, rac.getFilePointer());
}
ManglingFileSystemProvider.readExtraFileContent = true;
try (RandomAccessFile rac = new RandomAccessFile(file, "r")) {
rac.readLine();
assertEquals(ManglingFileSystemProvider.extraContent.length(), rac.getFilePointer());
}
}
@Test
public void length() throws Exception {
File file = temporaryFolder.newFile();
String content = "hello";
Files.writeString(file.toPath(), content);
ManglingFileSystemProvider.readExtraFileContent = true;
try (RandomAccessFile rac = new RandomAccessFile(file, "r")) {
assertEquals(content.length() + ManglingFileSystemProvider.extraContent.length(), rac.length());
}
}
@Test
public void read() throws Exception {
File file = temporaryFolder.newFile();
ManglingFileSystemProvider.readExtraFileContent = true;
try (RandomAccessFile rac = new RandomAccessFile(file, "r")) {
String extraContent = ManglingFileSystemProvider.extraContent;
for (int i = 0; i < extraContent.length(); i++) {
assertEquals((int) extraContent.charAt(i), rac.read());
}
assertEquals(-1, rac.read());
}
}
@Test
public void readFully() throws Exception {
File file = temporaryFolder.newFile();
Files.writeString(file.toPath(), "adapters everywhere");
ManglingFileSystemProvider.mangleFileContent = true;
try (RandomAccessFile rac = new RandomAccessFile(file, "r")) {
byte[] data = new byte[10];
rac.readFully(data);
assertEquals("4d4p73r5 3", new String(data));
Arrays.fill(data, (byte)' ');
try {
rac.readFully(data);
fail("An error should have been thrown but wasn't");
} catch (EOFException ignored) {
// Nothing.
}
assertEquals("v3rywh3r3 ", new String(data));
}
}
@Test
public void seek() throws Exception {
File file = temporaryFolder.newFile();
ManglingFileSystemProvider.readExtraFileContent = true;
try (RandomAccessFile rac = new RandomAccessFile(file, "r")) {
String extraContent = ManglingFileSystemProvider.extraContent;
for (int i = extraContent.length() - 1; i >= 0; i--) {
rac.seek(i);
assertEquals(extraContent.charAt(i), (char) rac.readByte());
}
}
}
@Test
public void setLength() throws Exception {
String extraContent = ManglingFileSystemProvider.extraContent;
assertTrue(extraContent.length() > 2);
assertTrue(extraContent.length() < 11);
File file = temporaryFolder.newFile();
String content = "hello";
Files.writeString(file.toPath(), content);
ManglingFileSystemProvider.mangleFileContent = true;
ManglingFileSystemProvider.readExtraFileContent = true;
try (RandomAccessFile rac = new RandomAccessFile(file, "rw")) {
assertEquals(content.length() + extraContent.length(), rac.length());
rac.setLength(content.length() + 2);
assertEquals(content.length() + 2, rac.length());
rac.seek(0);
assertEquals("h3110" + extraContent.substring(0, 2), rac.readLine());
}
ManglingFileSystemProvider.readExtraFileContent = false;
Files.writeString(file.toPath(), content);
try (RandomAccessFile rac = new RandomAccessFile(file, "rw")) {
assertEquals(content.length(), rac.length());
rac.setLength(11);
assertEquals(11, rac.length());
rac.seek(0);
byte[] buffer = new byte[1234];
try {
rac.readFully(buffer);
fail("EOFException wasn't thrown");
} catch (EOFException ignored) {
// Expected behavior.
}
assertEquals("h3110\0\0\0\0\0\0", new String(buffer, 0, 11));
// setLength should keep the offset.
rac.seek(0);
assertEquals('h', rac.readByte());
rac.setLength(17);
assertEquals('3', rac.readByte());
rac.setLength(3);
assertEquals('1', rac.readByte());
try {
rac.readByte();
fail("EOFException wasn't thrown");
} catch (EOFException ignored) {
// Expected behavior.
}
}
}
@Test
public void writeSingleByte() throws Exception {
File file = temporaryFolder.newFile();
ManglingFileSystemProvider.mangleFileContent = true;
try (RandomAccessFile rac = new RandomAccessFile(file, "rw")) {
rac.write('f');
rac.write('o');
rac.write('o');
rac.write('b');
rac.write('a');
rac.write('r');
}
ManglingFileSystemProvider.mangleFileContent = false;
assertEquals("f00b4r", Files.readString(file.toPath()));
}
@Test
public void writeBytes() throws Exception {
File file = temporaryFolder.newFile();
ManglingFileSystemProvider.mangleFileContent = true;
try (RandomAccessFile rac = new RandomAccessFile(file, "rw")) {
rac.writeBytes("herpderp");
}
ManglingFileSystemProvider.mangleFileContent = false;
assertEquals("h3rpd3rp", Files.readString(file.toPath()));
}
@Test
public void testDeletionOfLockedFile() throws Exception {
Assume.assumeTrue("Windows-only test", System.getProperty("os.name").toLowerCase().startsWith("win"));
File file = temporaryFolder.newFile();
try (RandomAccessFile rac = new RandomAccessFile(file, "rw");
FileLock ignored = rac.getChannel().lock()) {
assertFalse(file.delete());
}
}
}

View File

@@ -1,56 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 testNio;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
class ManglingBasicFileAttributeView implements BasicFileAttributeView {
private final BasicFileAttributeView view;
ManglingBasicFileAttributeView(BasicFileAttributeView view) {
this.view = view;
}
@Override
public String name() {
return view.name();
}
@Override
public BasicFileAttributes readAttributes() throws IOException {
return new ManglingBasicFileAttributes(view.readAttributes());
}
@Override
public void setTimes(FileTime lastModifiedTime, FileTime lastAccessTime, FileTime createTime) throws IOException {
if (ManglingFileSystemProvider.prohibitFileTreeModifications) {
throw new AccessDeniedException(null, null, "Test: Prohibiting file tree modifications");
}
view.setTimes(lastModifiedTime, lastAccessTime, createTime);
}
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 testNio;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
class ManglingBasicFileAttributes implements BasicFileAttributes {
private final BasicFileAttributes attrs;
ManglingBasicFileAttributes(BasicFileAttributes attrs) {
this.attrs = attrs;
}
@Override
public FileTime lastModifiedTime() {
return attrs.lastModifiedTime();
}
@Override
public FileTime lastAccessTime() {
return attrs.lastAccessTime();
}
@Override
public FileTime creationTime() {
return attrs.creationTime();
}
@Override
public boolean isRegularFile() {
return attrs.isRegularFile() && !ManglingFileSystemProvider.allFilesAreEmptyDirectories;
}
@Override
public boolean isDirectory() {
return attrs.isDirectory() || ManglingFileSystemProvider.allFilesAreEmptyDirectories;
}
@Override
public boolean isSymbolicLink() {
return attrs.isSymbolicLink() && !ManglingFileSystemProvider.denyAccessToEverything;
}
@Override
public boolean isOther() {
return attrs.isOther() && !ManglingFileSystemProvider.denyAccessToEverything;
}
@Override
public long size() {
return attrs.size();
}
@Override
public Object fileKey() {
return attrs.fileKey();
}
}

View File

@@ -1,79 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 testNio;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.NoSuchElementException;
class ManglingDirectoryStream implements DirectoryStream<Path> {
private final ManglingFileSystem manglingFileSystem;
private final ManglingPath dir;
private final DirectoryStream<Path> delegateResult;
private boolean addEliteElement = ManglingFileSystemProvider.addEliteToEveryDirectoryListing;
public ManglingDirectoryStream(ManglingFileSystem manglingFileSystem, ManglingPath dir, DirectoryStream<Path> delegateResult) {
this.manglingFileSystem = manglingFileSystem;
this.dir = dir;
this.delegateResult = delegateResult;
}
@Override
public void close() throws IOException {
delegateResult.close();
}
@Override
public Iterator<Path> iterator() {
return new ManglingPathIterator();
}
class ManglingPathIterator implements Iterator<Path> {
private final Iterator<Path> delegateIterator = delegateResult.iterator();
@Override
public boolean hasNext() {
if (delegateIterator.hasNext()) return true;
if (addEliteElement) {
addEliteElement = false;
return true;
}
return false;
}
@Override
public Path next() {
try {
return new ManglingPath(manglingFileSystem, delegateIterator.next());
} catch (NoSuchElementException err) {
if (ManglingFileSystemProvider.addEliteToEveryDirectoryListing) {
return dir.resolve("37337");
}
throw err;
}
}
}
}

View File

@@ -1,75 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 testNio;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.nio.file.attribute.DosFileAttributeView;
import java.nio.file.attribute.DosFileAttributes;
class ManglingDosFileAttributeView extends ManglingBasicFileAttributeView implements DosFileAttributeView {
private final DosFileAttributeView view;
ManglingDosFileAttributeView(DosFileAttributeView view) {
super(view);
this.view = view;
}
@Override
public DosFileAttributes readAttributes() throws IOException {
return new ManglingDosFileAttributes(view.readAttributes());
}
@Override
public void setReadOnly(boolean value) throws IOException {
if (ManglingFileSystemProvider.prohibitFileTreeModifications) {
throw new AccessDeniedException(null, null, "Test: Prohibiting file tree modifications");
}
view.setReadOnly(value);
}
@Override
public void setHidden(boolean value) throws IOException {
if (ManglingFileSystemProvider.prohibitFileTreeModifications) {
throw new AccessDeniedException(null, null, "Test: Prohibiting file tree modifications");
}
view.setHidden(value);
}
@Override
public void setSystem(boolean value) throws IOException {
if (ManglingFileSystemProvider.prohibitFileTreeModifications) {
throw new AccessDeniedException(null, null, "Test: Prohibiting file tree modifications");
}
view.setSystem(value);
}
@Override
public void setArchive(boolean value) throws IOException {
if (ManglingFileSystemProvider.prohibitFileTreeModifications) {
throw new AccessDeniedException(null, null, "Test: Prohibiting file tree modifications");
}
view.setArchive(value);
}
}

View File

@@ -1,55 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 testNio;
import java.nio.file.attribute.DosFileAttributes;
class ManglingDosFileAttributes extends ManglingBasicFileAttributes implements DosFileAttributes {
private final DosFileAttributes attrs;
ManglingDosFileAttributes(DosFileAttributes attrs) {
super(attrs);
this.attrs = attrs;
}
@Override
public boolean isReadOnly() {
return attrs.isReadOnly() && !ManglingFileSystemProvider.denyAccessToEverything;
}
@Override
public boolean isHidden() {
return attrs.isHidden();
}
@Override
public boolean isArchive() {
return attrs.isArchive();
}
@Override
public boolean isSystem() {
return attrs.isSystem();
}
}

View File

@@ -1,205 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 testNio;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.StandardCharsets;
public class ManglingFileChannel extends FileChannel {
private final FileChannel delegateChannel;
private byte[] extraBytes;
private int extraBytesPosition = -1;
public ManglingFileChannel(FileChannel delegateChannel) {
this.delegateChannel = delegateChannel;
if (ManglingFileSystemProvider.readExtraFileContent) {
extraBytes = ManglingFileSystemProvider.extraContent.getBytes(StandardCharsets.UTF_8);
} else {
extraBytes = new byte[0];
}
}
@Override
public int read(ByteBuffer dst) throws IOException {
int read = delegateChannel.read(dst);
if (ManglingFileSystemProvider.mangleFileContent) {
for (int i = 0; i < read; i++) {
dst.put(i, (byte) ManglingFileSystemProvider.mangle(dst.get(i)));
}
}
if (!dst.hasRemaining()) {
return read;
}
if (extraBytesPosition == -1) {
extraBytesPosition = 0;
}
if (extraBytesPosition < extraBytes.length) {
if (read == -1) {
read = 0;
}
do {
dst.put(extraBytes[extraBytesPosition++]);
read++;
} while (dst.hasRemaining() && extraBytesPosition < extraBytes.length);
}
return read;
}
@Override
public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public int write(ByteBuffer src) throws IOException {
if (ManglingFileSystemProvider.mangleFileContent) {
byte[] srcArray = new byte[src.remaining()];
src.get(srcArray);
src = ByteBuffer.wrap(ManglingFileSystemProvider.mangle(srcArray));
}
return delegateChannel.write(src);
}
@Override
public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public long position() throws IOException {
long delegatePosition = delegateChannel.position();
if (extraBytesPosition != -1) {
return extraBytesPosition + delegatePosition;
}
return delegatePosition;
}
@Override
public FileChannel position(long newPosition) throws IOException {
long size = delegateChannel.size();
if (newPosition > size) {
assert newPosition <= size + extraBytes.length;
delegateChannel.position(size);
extraBytesPosition = (int)(newPosition - size);
} else {
extraBytesPosition = -1;
delegateChannel.position(newPosition);
}
return this;
}
@Override
public long size() throws IOException {
return delegateChannel.size() + extraBytes.length;
}
@Override
public FileChannel truncate(long size) throws IOException {
long actualSize = delegateChannel.size();
if (size < actualSize) {
delegateChannel.truncate(size);
extraBytesPosition = -1;
} else {
size -= actualSize;
if (size < extraBytes.length) {
byte[] newExtraBytes = new byte[(int)size];
System.arraycopy(extraBytes, 0, newExtraBytes, 0, (int)size);
extraBytes = newExtraBytes;
extraBytesPosition = Math.min(extraBytesPosition, extraBytes.length - 1);
}
}
return this;
}
@Override
public void force(boolean metaData) throws IOException {
delegateChannel.force(metaData);
}
@Override
public long transferTo(long position, long count, WritableByteChannel target) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public long transferFrom(ReadableByteChannel src, long position, long count) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public int read(ByteBuffer dst, long position) throws IOException {
int read = delegateChannel.read(dst, position);
if (ManglingFileSystemProvider.mangleFileContent) {
for (int i = 0; i < dst.remaining(); i++) {
dst.put(i, (byte) ManglingFileSystemProvider.mangle(dst.get(i)));
}
}
if (dst.hasRemaining() && extraBytesPosition == -1) {
extraBytesPosition = 0;
}
while (dst.hasRemaining() && extraBytesPosition < extraBytes.length) {
dst.put(extraBytes[extraBytesPosition++]);
read++;
}
return read;
}
@Override
public int write(ByteBuffer src, long position) throws IOException {
if (ManglingFileSystemProvider.mangleFileContent) {
byte[] srcArray = new byte[src.remaining()];
src.get(srcArray);
src = ByteBuffer.wrap(ManglingFileSystemProvider.mangle(srcArray));
return delegateChannel.write(src);
}
return delegateChannel.write(src, position);
}
@Override
public MappedByteBuffer map(MapMode mode, long position, long size) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public FileLock lock(long position, long size, boolean shared) throws IOException {
return delegateChannel.lock(position, size, shared);
}
@Override
public FileLock tryLock(long position, long size, boolean shared) throws IOException {
return delegateChannel.tryLock(position, size, shared);
}
@Override
protected void implCloseChannel() throws IOException {
extraBytesPosition = -1;
delegateChannel.close();
}
}

View File

@@ -1,116 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 testNio;
import java.io.IOException;
import java.nio.file.FileStore;
import java.nio.file.FileSystem;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.nio.file.WatchService;
import java.nio.file.attribute.UserPrincipalLookupService;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class ManglingFileSystem extends FileSystem {
private final ManglingFileSystemProvider provider;
public ManglingFileSystem(ManglingFileSystemProvider fileSystemProvider) {
this.provider = fileSystemProvider;
}
@Override
public ManglingFileSystemProvider provider() {
return provider;
}
@Override
public void close() throws IOException {
provider.defaultFs.close();
}
@Override
public boolean isOpen() {
return provider.defaultFs.isOpen();
}
@Override
public boolean isReadOnly() {
return provider.defaultFs.isReadOnly();
}
@Override
public String getSeparator() {
return provider.defaultFs.getSeparator();
}
@Override
public Iterable<Path> getRootDirectories() {
Iterable<Path> delegateRoots = provider.defaultFs.getRootDirectories();
List<Path> result = new ArrayList<>();
for (Path delegateRoot : delegateRoots) {
result.add(new ManglingPath(this, delegateRoot));
}
if (ManglingFileSystemProvider.addEliteToEveryDirectoryListing) {
if (getSeparator().equals("/")) {
result.add(new ManglingPath(this, Paths.get("/31337")));
} else {
result.add(new ManglingPath(this, Paths.get("\\\\r00t\\31337\\")));
}
}
return result;
}
@Override
public Iterable<FileStore> getFileStores() {
return provider.defaultFs.getFileStores();
}
@Override
public Set<String> supportedFileAttributeViews() {
return provider.defaultFs.supportedFileAttributeViews();
}
@Override
public Path getPath(final String first, final String... more) {
return new ManglingPath(this, provider.defaultFs.getPath(first, more));
}
@Override
public PathMatcher getPathMatcher(String syntaxAndPattern) {
throw new UnsupportedOperationException();
}
@Override
public UserPrincipalLookupService getUserPrincipalLookupService() {
throw new UnsupportedOperationException();
}
@Override
public WatchService newWatchService() throws IOException {
throw new UnsupportedOperationException();
}
}

View File

@@ -1,306 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 testNio;
import java.io.IOException;
import java.net.URI;
import java.nio.channels.FileChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.AccessDeniedException;
import java.nio.file.AccessMode;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryStream;
import java.nio.file.FileStore;
import java.nio.file.FileSystem;
import java.nio.file.LinkOption;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.DosFileAttributeView;
import java.nio.file.attribute.DosFileAttributes;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.FileAttributeView;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.spi.FileSystemProvider;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
public class ManglingFileSystemProvider extends FileSystemProvider {
public static final String extraContent = "3x7r4";
private final static byte[] manglingTable = new byte[256];
public static boolean mangleFileContent = false;
public static boolean readExtraFileContent = false;
public static boolean manglePaths = false;
public static boolean mangleOnlyFileName = false;
public static boolean denyAccessToEverything = false;
public static boolean allFilesAreEmptyDirectories = false;
public static boolean prohibitFileTreeModifications = false;
public static boolean addEliteToEveryDirectoryListing = false;
static {
for (int i = 0; i < manglingTable.length; i++) {
manglingTable[i] = (byte) i;
}
manglingTable['A'] = '4';
manglingTable['a'] = '4';
manglingTable['E'] = '3';
manglingTable['e'] = '3';
manglingTable['G'] = '9';
manglingTable['g'] = '9';
manglingTable['I'] = '1';
manglingTable['i'] = '1';
manglingTable['L'] = '1';
manglingTable['l'] = '1';
manglingTable['O'] = '0';
manglingTable['o'] = '0';
manglingTable['S'] = '5';
manglingTable['s'] = '5';
manglingTable['T'] = '7';
manglingTable['t'] = '7';
manglingTable['Z'] = '2';
manglingTable['z'] = '2';
assert mangle("eleet haxor").equals("31337 h4x0r");
}
final FileSystemProvider defaultProvider;
final FileSystem defaultFs;
final ManglingFileSystem manglingFs = new ManglingFileSystem(this);
public ManglingFileSystemProvider(FileSystemProvider defaultProvider) {
super();
this.defaultProvider = defaultProvider;
this.defaultFs = defaultProvider.getFileSystem(URI.create("file:/"));
}
public static void resetTricks() {
mangleFileContent = false;
readExtraFileContent = false;
manglePaths = false;
mangleOnlyFileName = false;
denyAccessToEverything = false;
allFilesAreEmptyDirectories = false;
prohibitFileTreeModifications = false;
addEliteToEveryDirectoryListing = false;
}
public static String mangle(String source) {
StringBuilder sb = new StringBuilder();
for (char c : source.toCharArray()) {
if ((int) c < manglingTable.length) {
sb.append((char) manglingTable[c]);
} else {
sb.append(c);
}
}
return sb.toString();
}
public static byte[] mangle(byte[] source) {
byte[] result = new byte[source.length];
for (int i = 0; i < source.length; i++) {
result[i] = manglingTable[source[i]];
}
return result;
}
public static int mangle(int source) {
if (source >= 0 && source < manglingTable.length) {
return manglingTable[source];
}
return source;
}
static Path unwrap(Path path) {
if (path instanceof ManglingPath pcp) {
return pcp.delegate;
}
throw new IllegalArgumentException("Wrong path " + path + " (class: " + path.getClass() + ")");
}
@Override
public String getScheme() {
return defaultProvider.getScheme();
}
@Override
public FileSystem newFileSystem(URI uri, Map<String, ?> env) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public FileSystem getFileSystem(URI uri) {
URI rootUri = URI.create("file:/");
if (!Objects.equals(uri, rootUri)) {
throw new UnsupportedOperationException();
}
return manglingFs;
}
@Override
public Path getPath(URI uri) {
throw new UnsupportedOperationException();
}
@Override
public FileChannel newFileChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
return new ManglingFileChannel(defaultProvider.newFileChannel(unwrap(path), options, attrs));
}
@Override
public SeekableByteChannel newByteChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
return newFileChannel(path, options, attrs);
}
@Override
public DirectoryStream<Path> newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter) throws IOException {
return new ManglingDirectoryStream(manglingFs, (ManglingPath) dir, defaultProvider.newDirectoryStream(unwrap(dir), filter));
}
@Override
public void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException {
if (prohibitFileTreeModifications) {
throw new AccessDeniedException(dir.toString(), null, "Test: All file tree modifications are prohibited");
}
defaultProvider.createDirectory(unwrap(dir), attrs);
}
@Override
public void delete(Path path) throws IOException {
if (prohibitFileTreeModifications) {
throw new AccessDeniedException(path.toString(), null, "Test: All file tree modifications are prohibited");
}
defaultProvider.delete(unwrap(path));
}
@Override
public void copy(Path source, Path target, CopyOption... options) throws IOException {
if (prohibitFileTreeModifications) {
throw new AccessDeniedException(source.toString(), null, "Test: All file tree modifications are prohibited");
}
Path source2 = unwrap(source);
Path target2 = unwrap(target);
defaultProvider.copy(source2, target2, options);
}
@Override
public void move(Path source, Path target, CopyOption... options) throws IOException {
if (prohibitFileTreeModifications) {
throw new AccessDeniedException(source.toString(), null, "Test: All file tree modifications are prohibited");
}
Path source2 = unwrap(source);
Path target2 = unwrap(target);
defaultProvider.move(source2, target2, options);
}
@Override
public boolean isSameFile(Path path, Path path2) throws IOException {
Path source2 = unwrap(path);
Path target2 = unwrap(path2);
return defaultProvider.isSameFile(source2, target2);
}
@Override
public boolean isHidden(Path path) throws IOException {
return defaultProvider.isHidden(unwrap(path));
}
@Override
public FileStore getFileStore(Path path) throws IOException {
return defaultProvider.getFileStore(unwrap(path));
}
@Override
public void checkAccess(Path path, AccessMode... modes) throws IOException {
defaultProvider.checkAccess(unwrap(path), modes);
if (denyAccessToEverything) {
throw new AccessDeniedException(path.toString(), null, "Test: No access rules to anything");
}
}
@Override
public <V extends FileAttributeView> V getFileAttributeView(Path path, Class<V> type, LinkOption... options) {
return wrap(defaultProvider.getFileAttributeView(unwrap(path), type, options));
}
@Override
public <A extends BasicFileAttributes> A readAttributes(Path path, Class<A> type, LinkOption... options) throws IOException {
return wrap(defaultProvider.readAttributes(unwrap(path), type, options));
}
@Override
public Map<String, Object> readAttributes(Path path, String attributes, LinkOption... options) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void setAttribute(Path path, String attribute, Object value, LinkOption... options) throws IOException {
if (prohibitFileTreeModifications) {
throw new AccessDeniedException(path.toString(), null, "Test: All file tree modifications are prohibited");
}
defaultProvider.setAttribute(unwrap(path), attribute, value, options);
}
@Override
public boolean exists(Path path, LinkOption... options) {
return defaultProvider.exists(unwrap(path), options);
}
@Override
public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs) throws IOException {
if (prohibitFileTreeModifications) {
throw new AccessDeniedException(link.toString(), null, "Test: All file tree modifications are prohibited");
}
defaultProvider.createSymbolicLink(unwrap(link), unwrap(target), attrs);
}
private <A extends BasicFileAttributes> A wrap(A attrs) {
if (attrs instanceof DosFileAttributes dosAttrs) {
return (A) new ManglingDosFileAttributes(dosAttrs);
}
if (attrs instanceof PosixFileAttributes posixAttrs) {
return (A) new ManglingPosixFileAttributes(posixAttrs);
}
if (attrs instanceof BasicFileAttributes basicAttrs) {
return (A) new ManglingBasicFileAttributes(basicAttrs);
}
return attrs;
}
private <V extends FileAttributeView> V wrap(V view) {
if (view instanceof DosFileAttributeView dosView) {
return (V) new ManglingDosFileAttributeView(dosView);
}
if (view instanceof PosixFileAttributeView posixView) {
return (V) new ManglingPosixFileAttributeView(posixView);
}
if (view instanceof BasicFileAttributeView basicView) {
return (V) new ManglingBasicFileAttributeView(basicView);
}
return view;
}
}

View File

@@ -1,184 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 testNio;
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Objects;
public class ManglingPath implements Path {
final Path delegate;
private final ManglingFileSystem fileSystem;
ManglingPath(ManglingFileSystem fileSystem, Path delegate) {
this.fileSystem = fileSystem;
this.delegate = Objects.requireNonNull(delegate);
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
ManglingPath paths = (ManglingPath) o;
return Objects.equals(fileSystem, paths.fileSystem) && Objects.equals(delegate, paths.delegate);
}
@Override
public int hashCode() {
return Objects.hash(fileSystem, delegate);
}
@Override
public String toString() {
if (!ManglingFileSystemProvider.manglePaths) {
return delegate.toString();
} else if (!ManglingFileSystemProvider.mangleOnlyFileName) {
return ManglingFileSystemProvider.mangle(delegate.toString());
} else if (delegate.getParent() == null) {
return ManglingFileSystemProvider.mangle(delegate.toString());
} else {
String mangledFileName = ManglingFileSystemProvider.mangle(delegate.getFileName().toString());
return delegate.getParent().resolve(mangledFileName).toString();
}
}
@Override
public FileSystem getFileSystem() {
return fileSystem;
}
@Override
public boolean isAbsolute() {
return delegate.isAbsolute();
}
@Override
public Path getRoot() {
Path delegateRoot = delegate.getRoot();
if (delegateRoot == null) {
return null;
}
return new ManglingPath(fileSystem, delegateRoot);
}
@Override
public Path getFileName() {
return new ManglingPath(fileSystem, delegate.getFileName());
}
@Override
public Path getParent() {
Path parent = delegate.getParent();
if (parent != null) {
return new ManglingPath(fileSystem, parent);
} else {
return null;
}
}
@Override
public int getNameCount() {
return delegate.getNameCount();
}
@Override
public Path getName(int index) {
return new ManglingPath(fileSystem, delegate.getName(index));
}
@Override
public Path subpath(int beginIndex, int endIndex) {
return new ManglingPath(fileSystem, delegate.subpath(beginIndex, endIndex));
}
@Override
public boolean startsWith(Path other) {
if (other instanceof ManglingPath pcp) {
return delegate.startsWith(pcp.delegate);
}
throw new IllegalArgumentException("Wrong path " + other + " (class: " + other.getClass() + ")");
}
@Override
public boolean endsWith(Path other) {
if (other instanceof ManglingPath pcp) {
return delegate.endsWith(pcp.delegate);
}
throw new IllegalArgumentException("Wrong path " + other + " (class: " + other.getClass() + ")");
}
@Override
public Path normalize() {
return new ManglingPath(fileSystem, delegate.normalize());
}
@Override
public Path resolve(Path other) {
if (other instanceof ManglingPath pcp) {
return new ManglingPath(fileSystem, delegate.resolve(pcp.delegate));
}
throw new IllegalArgumentException("Wrong path " + other + " (class: " + other.getClass() + ")");
}
@Override
public Path relativize(Path other) {
if (other instanceof ManglingPath pcp) {
return new ManglingPath(fileSystem, delegate.relativize(pcp.delegate));
}
throw new IllegalArgumentException("Wrong path " + other + " (class: " + other.getClass() + ")");
}
@Override
public URI toUri() {
return delegate.toUri();
}
@Override
public Path toAbsolutePath() {
return new ManglingPath(fileSystem, delegate.toAbsolutePath());
}
@Override
public Path toRealPath(LinkOption... options) throws IOException {
return new ManglingPath(fileSystem, delegate.toRealPath(options));
}
@Override
public WatchKey register(WatchService watcher, WatchEvent.Kind<?>[] events, WatchEvent.Modifier... modifiers) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public int compareTo(Path other) {
if (other instanceof ManglingPath pcp) {
return delegate.compareTo(pcp.delegate);
}
return -1;
}
}

View File

@@ -1,70 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 testNio;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.nio.file.attribute.GroupPrincipal;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.UserPrincipal;
import java.util.Set;
class ManglingPosixFileAttributeView extends ManglingBasicFileAttributeView implements PosixFileAttributeView {
private final PosixFileAttributeView view;
ManglingPosixFileAttributeView(PosixFileAttributeView view) {
super(view);
this.view = view;
}
@Override
public PosixFileAttributes readAttributes() throws IOException {
return new ManglingPosixFileAttributes(view.readAttributes());
}
@Override
public void setPermissions(Set<PosixFilePermission> perms) throws IOException {
if (ManglingFileSystemProvider.prohibitFileTreeModifications) {
throw new AccessDeniedException(null, null, "Test: Prohibiting file tree modifications");
}
view.setPermissions(perms);
}
@Override
public void setGroup(GroupPrincipal group) throws IOException {
view.setGroup(group);
}
@Override
public UserPrincipal getOwner() throws IOException {
return view.getOwner();
}
@Override
public void setOwner(UserPrincipal owner) throws IOException {
view.setOwner(owner);
}
}

View File

@@ -1,57 +0,0 @@
/*
* Copyright 2025 JetBrains s.r.o.
* 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 testNio;
import java.nio.file.attribute.GroupPrincipal;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.UserPrincipal;
import java.util.Set;
class ManglingPosixFileAttributes extends ManglingBasicFileAttributes implements PosixFileAttributes {
private final PosixFileAttributes attrs;
ManglingPosixFileAttributes(PosixFileAttributes attrs) {
super(attrs);
this.attrs = attrs;
}
@Override
public UserPrincipal owner() {
return attrs.owner();
}
@Override
public GroupPrincipal group() {
return attrs.group();
}
@Override
public Set<PosixFilePermission> permissions() {
if (ManglingFileSystemProvider.denyAccessToEverything) {
return Set.of();
}
return attrs.permissions();
}
}

View File

@@ -2,6 +2,7 @@ java/awt/Choice/ChoiceHandleMouseEvent.java
java/awt/Choice/ChoiceHandleMouseEvent_2.java JBR-7174 windows-all
java/awt/Choice/SelectItem/SelectCurrentItemTest.java JBR-8333 windows-all
java/awt/Choice/SelectItem/SelectNewItemTest.java JBR-8387 windows-x64
java/awt/grab/SystemMenuTest.java JBR-8862 windows-x64
java/awt/Graphics/XORPaint.java#id0 JBR-7499 windows-x64
java/awt/Toolkit/LWCToolkitInvokeAndWaitTest.java nobug macosx-all,linux-all,windows-all
java/awt/Toolkit/AWTThreadingTest.java nobug macosx-all,linux-all,windows-all
@@ -14,7 +15,7 @@ java/awt/Modal/BlockedMouseInputTest.java JBR-8406 windows-x64
java/awt/Modal/BlockedMouseInputTest2.java JBR-8406 windows-x64
java/awt/Modal/BlockedMouseInputTest3.java JBR-8406 windows-x64
java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java#id0 JBR-8577 windows-x64
java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersInKeyEvent.java 8157147,JBR-8578 linux-all,windows-all,windows-x64
java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersInKeyEvent.java 8157147,JBR-8578,JBR-5397 linux-all,windows-all,windows-x64,macosx-all
java/awt/Paint/PaintNativeOnUpdate.java JBR-5397,JBR-7415 macosx-all,windows-x64
java/awt/PopupMenu/PopupMenuLocation.java JBR-5397,JBR-7375 macosx-all,windows-x64
java/awt/Robot/CheckCommonColors/CheckCommonColors.java JBR-5397,JBR-6092 macosx-all,windows-x64
@@ -39,6 +40,8 @@ javax/swing/JComboBox/8041909/ActionListenerExceptionTest.java JBR-5210 windows-
javax/swing/JComboBox/bug4996503.java JBR-7412 windows-x64
javax/swing/JComboBox/EditableComboBoxPopupPos.java JBR-7383 windows-x64
javax/swing/JComponent/7154030/bug7154030.java JBR-8384 windows-x64
javax/swing/JFileChooser/4966171/bug4966171.java JBR-8855 windows-x64
javax/swing/JFileChooser/FileChooserListenerLeak.java JBR-8855 windows-x64
javax/swing/JInternalFrame/Test6505027.java nobug macosx-all,linux-all,windows-all
javax/swing/JMenuBar/MenuBarRTLBug.java JBR-7385 windows-x64
javax/swing/JPopupMenu/4634626/bug4634626.java nobug macosx-all,linux-all,windows-all
@@ -47,6 +50,7 @@ javax/swing/JPopupMenu/6415145/bug6415145.java 8197552,JBR-5397 macosx-all,windo
javax/swing/JTree/4518432/JTreeNodeCopyPasteTest.java JBR-5397,JBR-8335 macosx-all,windows-all
javax/swing/text/StyledEditorKit/4506788/bug4506788.java JBR-7386 windows-x64
jb/java/awt/CustomTitleBar/HitTestNonClientArea.java JBR-8861 windows-x64
jb/java/awt/Desktop/AboutHandlerTest.java nobug macosx-all,linux-all,windows-all
jb/java/awt/Focus/NewFrameAfterDialogTest.java JBR-7387 windows-x64
jb/java/awt/Focus/ChainOfPopupsFocusTest.java JBR-8407 windows-x64
@@ -123,7 +127,6 @@ java/awt/List/ListMultipleSelectTest/ListMultipleSelectTest.java JBR-5555,JBR-53
java/awt/Mouse/EnterExitEvents/DragWindowTest.java 8253184,JBR-5397 macosx-all,windows-all
java/awt/Mouse/ExtraMouseClick/ExtraMouseClick.java 8253184,JBR-5709 windows-all,linux-all
java/awt/Mouse/MouseComboBoxTest/MouseComboBoxTest.java 8253184,JBR-6752,JBR-5397 windows-all,linux-all,macosx-all
java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersInKeyEvent.java JBR-5397 macosx-all
java/awt/Window/WindowOwnedByEmbeddedFrameTest/WindowOwnedByEmbeddedFrameTest.java JBR-5397 macosx-all
javax/accessibility/JSlider/AccessibleAction/JSliderAccessibleAction.java JBR-5397 macosx-all
javax/swing/JComboBox/6236162/bug6236162.java JBR-5210,JBR-5397 windows-all,macosx-all

View File

@@ -134,7 +134,7 @@ java/awt/TextArea/UsingWithMouse/SelectionAutoscrollTest.java JBR-7779 linux-all
javax/swing/JEditorPane/TestBrowserBGColor.java JBR-6697 linux-aarch64
javax/swing/plaf/nimbus/8041642/ScrollBarThumbVisibleTest.java JBR-6485 linux-all
javax/swing/plaf/nimbus/8041642/bug8041642.java JBR-6698 linux-all
javax/swing/UI/UnninstallUIMemoryLeaks/UnninstallUIMemoryLeaks.java JBR-5952,8340330,JBR-6274 windows-all,macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-all
javax/swing/UI/UnninstallUIMemoryLeaks/UnninstallUIMemoryLeaks.java JBR-5952,JBR-6274 windows-all,macosx-all
jb/java/awt/Focus/PopupIncomingFocusTest.java JBR-2651 generic-all
jb/java/awt/Window/UndecoratedDialogInTransientsChain.java JBR-6924 windows-all

View File

@@ -1,19 +1,22 @@
java/awt/Button/DisabledButtonPress.java JBR-5799,JBR-8858 windows-aarch64,windows-x64
java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java JBR-6857,JBR-5398 macosx-all,linux-all,windows-all
java/awt/Choice/ChoiceStaysOpenedOnTAB.java JBR-6284 linux-all
java/awt/Debug/X11Trace.java JBR-5442 linux-all
java/awt/EmbeddedFrame/GraphicsConfigTest/GraphicsConfigTest.java 8305515 linux-all
java/awt/event/ComponentEvent/TextComponentTextEventTest.java JBR-7141 windows-x64
java/awt/event/KeyEvent/KeyEventLocationTest.java JBR-5916,JBR-7141 linux-all,windows-all
java/awt/grab/SystemMenuTest.java JBR-8829 windows-x64
java/awt/Multiscreen/MultiScreenInsetsTest/MultiScreenInsetsTest.java JBR-7782 linux-x64
java/awt/Multiscreen/MultiScreenLocationTest/MultiScreenLocationTest.java JBR-6058,JBR-6664 windows-all,linux-all,macosx-all
java/awt/Multiscreen/WindowGCChangeTest/WindowGCChangeTest.java JBR-5531 macosx-all,linux-all
java/awt/Focus/6981400/Test1.java 8029675,JBR-5510,JBR-6702 windows-all,macosx-all,linux-5.18.2-arch1-1,linux-all
java/awt/Focus/NullActiveWindowOnFocusLost/NullActiveWindowOnFocusLost.java JBR-8896 windows-x64
java/awt/Focus/TemporaryLostComponentDeadlock.java JBR-5734 windows-all
java/awt/Frame/GetGraphicsStressTest/GetGraphicsStressTest.java JBR-5117,JBR-6509 linux-all,generic-all
java/awt/Frame/MaximizedToOppositeScreen/MaximizedToOppositeScreenSmall.java JBR-4379 windows-all
java/awt/Frame/SetMaximizedBounds/SetMaximizedBounds.java JBR-4379 windows-all
java/awt/FullScreen/CurrentDisplayModeTest/CurrentDisplayModeTest.java JBR-5059 linux-all
java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java JBR-4275,JBR-4880,JBR-7249,JBR-8278 linux-all,windows-all,macosx-all
java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java JBR-4275,JBR-4880,JBR-7249 linux-all,windows-all
java/awt/FullScreen/MultimonFullscreenTest/MultimonDeadlockTest.java JBR-4379 windows-all
java/awt/Graphics2D/DrawString/DisposerTest.java JBR-5442 linux-all
java/awt/GraphicsDevice/DisplayModes/CompareToXrandrTest.java JBR-5062 linux-all
@@ -22,7 +25,7 @@ java/awt/GraphicsDevice/IncorrectDisplayModeExitFullscreen.java JBR-6336 macosx-
java/awt/datatransfer/Clipboard/GetContentsInterruptedTest.java JBR-5086 linux-5.15.0-46-generic Ubuntu 20.04
java/awt/Robot/Delay/InterruptOfDelay.java 8265986,JBR-8148 macosx-all,linux-x64
java/awt/Robot/MouseLocationOnScreen/MouseLocationOnScreen.java JBR-5390 macosx-all,linux-all
java/awt/Robot/NonEmptyErrorStream.java 8340330,JBR-5442,JBR-5510 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,linux-5.18.2-arch1-1
java/awt/Robot/NonEmptyErrorStream.java JBR-5442,JBR-5510 macosx-15.4,linux-5.18.2-arch1-1
java/awt/Robot/RobotMoveMultiscreen.java JBR-5442 linux-all
java/awt/Robot/SpuriousMouseEvents/SpuriousMouseEvents.java JBR-6572 linux-all
java/awt/TextArea/UsingWithMouse/SelectionAutoscrollTest.java JBR-7822 linux-x64
@@ -116,6 +119,7 @@ javax/swing/JDialog/Transparency/TransparencyTest.java 8253184,JBR-5510 windows-
javax/swing/JEditorPane/TestBrowserBGColor.java JBR-5510 linux-all
javax/swing/JInternalFrame/5066752/bug5066752.java 8253184,JBR-5510 windows-all,linux-all
javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java JBR-5510 linux-all
javax/swing/JInternalFrame/bug4732229.java JBR-8897 windows-x64
javax/swing/JMenu/JMenuSelectedColorTest.java JBR-5510 linux-all
javax/swing/JPasswordField/TestSelectedTextBackgroundColor.java nobug linux-all
javax/swing/JProgressBar/TestJProgressBarHighlightColor.java nobug linux-all
@@ -132,7 +136,7 @@ javax/swing/plaf/basic/BasicHTML/4251579/bug4251579.java 8253184,JBR-5510 window
javax/swing/plaf/metal/MetalGradient/8163193/ButtonGradientTest.java 8253184,JBR-5510 windows-all,linux-all
javax/swing/plaf/nimbus/8041642/bug8041642.java 8253184,JBR-5510 windows-all,linux-all
javax/swing/plaf/nimbus/8041642/ScrollBarThumbVisibleTest.java JBR-5510 linux-all
javax/swing/plaf/nimbus/8057791/bug8057791.java 8253184,JBR-5510 windows-all,linux-all
javax/swing/plaf/nimbus/8057791/bug8057791.java 8253184,JBR-5510,JBR-8300 windows-all,linux-all,macosx-aarch64
javax/swing/text/html/CSS/4530474/bug4530474.java JBR-5510,JBR-5951 linux-all,windows-x64
javax/swing/text/html/StyleSheet/bug4936917.java JBR-899,JBR-5510 windows-all,linux-all
jb/java/awt/MouseInfo/GetPointerInfoTest.java nobug linux-all

View File

@@ -42,6 +42,7 @@ javax/imageio/plugins/shared/ImageWriterCompressionTest.java JBR-8804 linux-all
javax/swing/border/Test4129681.java JBR-7787 linux-all
javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java JBR-8806 linux-all
javax/swing/JComboBox/6559152/bug6559152.java JBR-8807 linux-all
javax/swing/JComboBox/DisabledComboBoxFontTestAuto.java JBR-8808 linux-all
javax/swing/JComboBox/TestComboBoxComponentRendering.java initial_runs generic-all
javax/swing/JEditorPane/4666101/JEditorPaneNavigationTest.java initial_runs generic-all
javax/swing/JEditorPane/6917744/bug6917744.java initial_runs generic-all

View File

@@ -158,7 +158,7 @@ java/awt/Frame/DisposeTest.java JBR-7937,JBR-8718 macosx-aarch64,linux-5.18.2-ar
java/awt/Frame/GetGraphicsStressTest/GetGraphicsStressTest.java JBR-6509 generic-all
java/awt/Frame/HideMaximized/HideMaximized.java JBR-8310 linux-all
java/awt/Frame/MaximizeUndecoratedTest.java JBR-8064 linux-all
java/awt/Frame/MaximizedToIconified/MaximizedToIconified.java 8296972 macosx-all
java/awt/Frame/MaximizedToIconified/MaximizedToIconified.java JBR-7509,JBR-8889 macosx-15.4.1,macosx-all
java/awt/Frame/MaximizedToMaximized/MaximizedToMaximized.java JBR-7786,JBR-7947 linux-all,macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4
java/awt/Frame/MaximizedToOppositeScreen/MaximizedToOppositeScreenBig.java JBR-5303 windows-all
java/awt/Frame/MaximizedUndecorated/MaximizedUndecorated.java 8022302 generic-all
@@ -179,7 +179,6 @@ java/awt/dnd/ModalDialogDeadlockTest.java JBR-6776 windows-all
java/awt/dnd/ModalDialogOnDropDeadlockTest.java JBR-6529 windows-all
java/awt/dnd/ModalDialogOnDragDeadlockTest.java JBR-6996 windows-all
java/awt/dnd/NestedHeavyweightDropTargetTest.java JBR-6580 windows-all
java/awt/dnd/NextDropActionTest/NextDropActionTest.java 8313633 macosx-aarch64
java/awt/dnd/URIListBetweenJVMsTest/URIListBetweenJVMsTest.java 8171510,JBR-881 macosx-all,linux-all
javax/swing/dnd/7171812/bug7171812.java 8253184 windows-all
java/awt/Focus/ChildWindowFocusTest/ChildWindowFocusTest.java JBR-5545 linux-all,windows-all
@@ -200,7 +199,7 @@ java/awt/Focus/TypeAhead/TestFocusFreeze.java JBR-5856 windows-all
java/awt/Focus/WindowInitialFocusTest/WindowInitialFocusTest.java JBR-69 windows-all
java/awt/Focus/WrongKeyTypedConsumedTest/WrongKeyTypedConsumedTest.java 8169096,JBR-4880,JBR-5387 macosx-all,windows-all,linux-all
java/awt/EventQueue/6980209/bug6980209.java 8198615 macosx-all
java/awt/Frame/ExceptionOnSetExtendedStateTest/ExceptionOnSetExtendedStateTest.java 8198237 macosx-all
java/awt/Frame/ExceptionOnSetExtendedStateTest/ExceptionOnSetExtendedStateTest.java JBR-8885 macosx-all
java/awt/Frame/SetMinimumSizeTest/SetMinimumSizeTest2.java JBR-5210 windows-all
java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java JBR-5210,JBR-6126 windows-all,linux-5.18.2-arch1-1,macosx-all
java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java 7080150,JBR-4880,8253184,JBR-5510 macosx-all,windows-all,linux-5.18.2-arch1-1
@@ -265,8 +264,8 @@ java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java 8073636,JBR-4211
java/awt/EventDispatchThread/PropertyPermissionOnEDT/PropertyPermissionOnEDT.java JBR-5225 windows-all
java/awt/FullScreen/AltTabCrashTest/AltTabCrashTest.java JBR-4905 windows-all,linux-all
java/awt/FullScreen/FullScreenInsets/FullScreenInsets.java 7019055,8266245 windows-all,linux-all,macosx-all
java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java JBR-4275,JBR-4880,JBR-8278 linux-all,windows-all,macosx-all
java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java 7188711,8253184,JBR-8278 linux-all,windows-all,macosx-all
java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java JBR-4275,JBR-4880 linux-all,windows-all
java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java 7188711,8253184 linux-all,windows-all
java/awt/FullScreen/UninitializedDisplayModeChangeTest/UninitializedDisplayModeChangeTest.java 7188711,8273617,JBR-4880,8253184 macosx-all,linux-all,windows-all
java/awt/Focus/8013611/JDK8013611.java 8175366 windows-all,macosx-all
java/awt/Focus/6401036/InputVerifierTest2.java JBR-7537 linux-all
@@ -372,7 +371,6 @@ sun/java2d/SunGraphics2D/DrawImageBilinear.java 8297175 linux-all
java/awt/Graphics2D/CopyAreaOOB.java JBR-5354 macosx-all,windows-all,linux-5.18.2-arch1-1
java/awt/Graphics2D/DrawString/DisposerTest.java JBR-5010,JBR-5510 linux-aarch64,linux-5.18.2-arch1-1
java/awt/Graphics2D/DrawString/DrawRotatedStringUsingRotatedFont.java 8266283 generic-all
java/awt/Graphics2D/ScaledTransform/ScaledTransform.java 8277240 linux-all
sun/java2d/SunGraphics2D/PolyVertTest.java 6986565 generic-all
sun/java2d/SunGraphics2D/SimplePrimQuality.java 6992007 generic-all
sun/java2d/SunGraphics2D/SourceClippingBlitTest/SourceClippingBlitTest.java 8196185 generic-all
@@ -406,7 +404,7 @@ java/awt/Frame/MiscUndecorated/ActiveSwingWindowTest.java JBR-5210 windows-all
java/awt/Frame/MiscUndecorated/FrameCloseTest.java JBR-5210 windows-all
java/awt/Frame/MiscUndecorated/RepaintTest.java 8266244,JBR-5786 macosx-aarch64,generic-all
java/awt/Robot/HiDPIMouseClick/HiDPIRobotMouseClick.java 8253184 windows-all
java/awt/Robot/NonEmptyErrorStream.java 8340330,JBR-5510 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,linux-5.18.2-arch1-1
java/awt/Robot/NonEmptyErrorStream.java JBR-5510 linux-5.18.2-arch1-1
java/awt/Robot/RobotExtraButton/RobotExtraButton.java JBR-6554 linux-all
java/awt/Modal/FileDialog/FileDialogAppModal1Test.java 7186009,8253184 macosx-all,windows-all
java/awt/Modal/FileDialog/FileDialogAppModal2Test.java 7186009,8253184 macosx-all,windows-all
@@ -677,7 +675,7 @@ java/awt/JAWT/JAWT.sh 8197798 windows-all,linux-all
java/awt/datatransfer/ConstructFlavoredObjectTest/ConstructFlavoredObjectTest.java 8202860 linux-all
java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java 8202882,JBR-1147 linux-all,macosx-all
java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java 7124275 macosx-all
java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java 8280392
java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java JBR-7299 linux-all
java/awt/Focus/NoFocusOwnerAWTTest.java JBR-5825 windows-all
java/awt/Focus/NoFocusOwnerSwingTest.java JBR-5825 windows-all
java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java 6848810,JBR-5210 macosx-all,linux-all,windows-all
@@ -695,7 +693,6 @@ java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsDocModalTest.java 816
java/awt/Frame/DecoratedFrameInsets/DecoratedFrameInsetsTest.java JBR-5205 linux-5.4.0-1103-aws
java/awt/Frame/DisposeParentGC/DisposeParentGC.java 8079786 macosx-all
java/awt/GraphicsDevice/CheckDisplayModes.java 8266242,JBR-8183 macosx-aarch64,macosx-x64
java/awt/GraphicsDevice/DisplayModes/CycleDMImage.java 7099223,8274106 macosx-all,linux-all,windows-all
java/awt/GraphicsDevice/DisplayModes/ExtraAllocationTest.java JBR-6384 macosx-all
java/awt/keyboard/AllKeyCode/AllKeyCode.java 8242930 macosx-all
@@ -731,7 +728,6 @@ java/awt/wakefield/ScreenCapture.java JBR-5653 linux-all
# Several tests which fail sometimes on macos11
java/awt/Window/MainKeyWindowTest/TestMainKeyWindow.java 8265985 macosx-all
java/awt/security/WarningWindowDisposeTest/WarningWindowDisposeCrashTest.java JBR-5225 windows-all
java/awt/security/WarningWindowDisposeTest/WarningWindowDisposeTest.java 8266059 macosx-all
java/awt/Robot/Delay/InterruptOfDelay.java 8265986 macosx-all
java/awt/MenuBar/MenuBarSetFont/MenuBarSetFont.java JBR-6660 windows-all
java/awt/MenuBar/TestNoScreenMenuBar.java 8265987 macosx-all
@@ -834,19 +830,19 @@ java/net/DatagramSocket/DatagramSocketMulticasting.java 8144003,JBR-8455
java/net/MulticastSocket/NoLoopbackPackets.java 7122846 macosx-all
java/net/MulticastSocket/Promiscuous.java 8308807,JBR-8455 aix-ppc64,macosx-all
java/net/MulticastSocket/SetLoopbackModeIPv4.java JBR-8455 macosx-all
java/net/MulticastSocket/SetOutgoingIf.java JBR-8828 macosx-x64
java/net/SocketPermission/SocketPermissionTest.java JBR-8455 macosx-all
java/net/MulticastSocket/SetLoopbackMode.java 7122846 macosx-all
java/net/MulticastSocket/SetOutgoingIf.java 8321217,JBR-8828 macosx-14.7.3,macosx-14.7.4,macosx-14.7.5,macosx-all
java/net/MulticastSocket/Test.java 7145658 macosx-all
java/net/ServerSocket/AcceptInheritHandle.java 8211854 aix-ppc64
javax/net/ssl/SSLSocket/Tls13PacketSize.java 8354235 windows-all
############################################################################
# jdk_nio
java/nio/channels/AsynchronousSocketChannel/StressLoopback.java 8211851,JBR-8817 aix-ppc64,windows-aarch64
java/nio/channels/AsynchronousSocketChannel/StressLoopback.java JBR-8817 windows-aarch64
java/nio/channels/DatagramChannel/AdaptorMulticasting.java 8144003,JBR-8455,JBR-8456,8308807 macosx-all,aix-ppc64
java/nio/channels/DatagramChannel/BasicMulticastTests.java 8144003 macosx-all
@@ -861,8 +857,6 @@ java/nio/channels/Selector/Wakeup.java 6963118 windows-
java/nio/file/WatchService/JNIChecks.java JBR-8457 generic-all
java/nio/file/WatchService/WithSecurityManager.java nobug macosx-all
jdk/nio/zipfs/TestLocOffsetFromZip64EF.java 8301183 linux-all
############################################################################
# jdk_rmi
@@ -901,17 +895,11 @@ com/sun/nio/sctp/SctpChannel/SocketOptionTests.java 8141694 linux-al
security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#actalisauthenticationrootca 8324583 generic-all
security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#digicerttlseccrootg5 8324583 generic-all
security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#digicerttlsrsarootg5 8324583 generic-all
security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#globalsigneccrootcar4 8328825 generic-all
security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#gtsrootcar1 8328825 generic-all
security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#gtsrootcar2 8328825 generic-all
security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#gtsrootecccar3 8328825 generic-all
security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#gtsrootecccar4 8328825 generic-all
security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#microsoftecc2017 8328825 generic-all
security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#quovadisrootca1g3 8324583 generic-all
security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#sslrooteccca 8333788 generic-all
security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#sslrootevrsaca 8333788 generic-all
security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#teliasonerarootcav1 8328825 generic-all
sun/security/lib/cacerts/VerifyCACerts.java 8357195 generic-all
sun/security/mscapi/CngCipher.java JBR-8508 windows-all
sun/security/smartcardio/TestChannel.java 8039280 generic-all
@@ -1066,7 +1054,7 @@ javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentWindowClickSwing.java
# The next test below is an intermittent failure
javax/swing/JTree/DnD/LastNodeLowerHalfDrop.java 8159131 linux-all
javax/swing/JTree/4330357/bug4330357.java 8253184,JBR-6466 windows-all,linux-all
javax/swing/JTree/4633594/JTreeFocusTest.java 7105441,8173125,JBR-5210 macosx-all,windows-all
javax/swing/JTree/4633594/JTreeFocusTest.java 7105441,JBR-5210 macosx-all,windows-all
javax/swing/JTree/4908142/bug4908142.java 8197552,JBR-151 windows-all
javax/swing/AbstractButton/6711682/bug6711682.java 8060765 windows-all,macosx-all,linux-5.15.0-39-generic,linux-5.15.0-33-generic,linux-5.19.0-1025-aws,linux-6.5.0-1024-aws
javax/swing/Action/8133039/bug8133039.java JBR-5210 windows-all
@@ -1077,7 +1065,6 @@ javax/swing/JColorChooser/Test6541987.java JBR-5210 windows-all
javax/swing/JColorChooser/Test7194184.java JBR-5210 windows-all
javax/swing/JColorChooser/Test8051548.java JBR-5210 windows-all
javax/swing/JEditorPane/bug4714674.java JBR-5810 windows-all
javax/swing/JComboBox/DisabledComboBoxFontTestAuto.java 8310072 linux-all,windows-all
javax/swing/JEditorPane/JEditorPaneGCSwitchTest/JEditorPaneGCSwitchTest_i18n.java JBR-912 windows-all
javax/swing/JEditorPane/JEditorPaneGCSwitchTest/JEditorPaneGCSwitchTest.java JBR-912 windows-all
javax/swing/JFileChooser/4524490/bug4524490.java JBR-5846 windows-all
@@ -1154,7 +1141,7 @@ javax/swing/text/JTextComponent/5074573/bug5074573.java CODETOOLS-7901623,JBR-53
javax/swing/text/JTextComponent/6361367/bug6361367.java JBR-5210,JBR-6687 windows-all,linux-5.18.2-arch1-1
javax/swing/text/View/8014863/bug8014863.java JBR-5541 windows-all,linux-all
javax/swing/text/View/8156217/FPMethodCalledTest.java JBR-5541 linux-all
javax/swing/UI/UnninstallUIMemoryLeaks/UnninstallUIMemoryLeaks.java JBR-5952,8340330 windows-all,macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4
javax/swing/UI/UnninstallUIMemoryLeaks/UnninstallUIMemoryLeaks.java JBR-5952 windows-all
javax/swing/UIDefaults/6795356/TableTest.java JBR-5767 windows-all
java/awt/Robot/HiDPIScreenCapture/HiDPIRobotScreenCaptureTest.java 8253184,JBR-1656 windows-all,linux-all
java/awt/Robot/HiDPIScreenCapture/ScreenCaptureTest.java 8253184,JBR-5510 windows-all,linux-5.18.2-arch1-1
@@ -1195,17 +1182,18 @@ java/text/Format/NumberFormat/Bug4944439.java JBR-8458 macosx-all
tools/jimage/VerifyJimage.java JBR-8453 generic-all
tools/jlink/JLinkReproducible3Test.java 8253688 linux-aarch64
tools/jlink/plugins/SystemModuleDescriptors/SystemModulesTest.java JBR-8465 generic-all
tools/jlink/plugins/SystemModuleDescriptors/SystemModulesTest.java JBR-4137 generic-all
tools/jlink/plugins/VendorInfoPluginsTest.java JBR-8783 windows-aarch64
tools/jpackage/share/AddLauncherTest.java#id1 JBR-8701 windows-all
tools/jpackage/share/IconTest.java JBR-8701 windows-all
tools/jpackage/share/MultiNameTwoPhaseTest.java JBR-8860 linux-aarch64
tools/jpackage/windows/Win8301247Test.java JBR-8708 windows-all
tools/launcher/Arrrghs.java JBR-8466 generic-all
tools/launcher/ChangeDataModel.java JBR-8467 generic-all
tools/launcher/HelpFlagsTest.java JBR-2053,JBR-8614 windows-all
tools/launcher/MultipleJRERemoved.java JBR-8468 generic-all
tools/launcher/Settings.java JBR-8469 generic-all
tools/launcher/TestSpecialArgs.java windows-all,linux-6.8.0-1028-aws,linux-5.15.0-1081-aws
tools/launcher/TestSpecialArgs.java windows-all,linux-aarch64
tools/launcher/VersionCheck.java JBR-2053 windows-all
############################################################################
@@ -1214,6 +1202,7 @@ tools/launcher/VersionCheck.java JBR-2053 windows-all
com/sun/jdi/FinalizerTest.java 8343606 generic-all
com/sun/jdi/RepStep.java 8043571 generic-all
com/sun/jdi/SetLocalWhileThreadInNative.java JBR-8537 generic-all
com/sun/jdi/InvokeHangTest.java 8218463 linux-all
@@ -1227,6 +1216,7 @@ com/sun/jdi/InvokeHangTest.java 8218463 linux-al
java/util/Locale/LocaleProvidersRun.java 8268379 macosx-x64
sun/util/locale/provider/CalendarDataRegression.java 8268379 macosx-x64
java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java JBR-8867 windows-aarch64
java/util/concurrent/forkjoin/AsyncShutdownNow.java 8286352 linux-all,windows-x64
java/util/concurrent/ExecutorService/CloseTest.java 8288899 macosx-aarch64
@@ -1241,7 +1231,7 @@ java/util/concurrent/ExecutorService/CloseTest.java 8288899 macosx-a
sun/tools/jhsdb/HeapDumpTest.java 8269881 windows-all
sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java JBR-6288 windows-all
sun/tools/jhsdb/JShellHeapDumpTest.java JBR-6288 windows-all
sun/tools/jstatd/TestJstatdRmiPort.java 8226420,8251259,8293577 generic-all
sun/tools/jstatd/TestJstatdRmiPort.java 8251259,8293577 generic-all
sun/tools/jstat/jstatLineCounts1.sh 8268211 linux-aarch64
sun/tools/jstat/jstatLineCounts2.sh 8268211 linux-aarch64
@@ -1291,7 +1281,7 @@ jdk/internal/platform/docker/TestPidsLimit.java 8311539 linux-all
# jdk_modules
jdk/modules/etc/JdkQualifiedExportTest.java JBR-4135 generic-all
jdk/modules/etc/UpgradeableModules.java JBR-8464 generic-all
jdk/modules/etc/UpgradeableModules.java JBR-4136 generic-all
############################################################################
@@ -1308,7 +1298,6 @@ java/awt/xembed/server/TestXEmbedServerJava.java 8001150,8004031 generic-all
javax/swing/JFileChooser/6698013/bug6698013.java 8024419 macosx-all
javax/swing/JColorChooser/8065098/bug8065098.java 8065647 macosx-all
java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java 8068378 generic-all
java/awt/dnd/DnDFileGroupDescriptor/DnDFileGroupDescriptor.html 8080185 macosx-all,linux-all
javax/swing/JTabbedPane/4666224/bug4666224.html 8144124 macosx-all
javax/swing/JTextArea/8149849/DNDTextToScaledArea.java 8253184 windows-all
javax/swing/JTextArea/7049024/bug7049024.java JBR-5836 linux-all
@@ -1327,7 +1316,7 @@ java/awt/font/OutlineTextRendererEmoji.java JBR-5009 linux-aarch64
java/awt/font/EmojiVariation.java JBR-5009,JBR-5510 linux-aarch64,linux-5.18.2-arch1-1
java/awt/font/TextLayout/TestSinhalaChar.java JBR-5103 generic-all
javax/swing/JTableHeader/6884066/bug6884066.java JBR-113 windows-all,linux-aarch64
javax/swing/JTableHeader/6889007/bug6889007.java 8310238,8253184,JBR-5387 macosx-all,windows-all,linux-all
javax/swing/JTableHeader/6889007/bug6889007.java 8253184,JBR-5387 windows-all,linux-all
javax/swing/JTextField/8036819/bug8036819.java JBR-6113 windows-all
javax/swing/JTree/4927934/bug4927934.java JBR-6114 windows-all
java/awt/TrayIcon/DragEventSource/DragEventSource.java 8252242 macosx-all
@@ -1451,9 +1440,7 @@ jb/javax/swing/JEditorPane/ZeroMargin.java JBR-2256 generic-all
jb/javax/swing/JPopupMenu/JPopupMenuOutOfWindowTest.java JBR-6682 windows-all,linux-all
jb/java/awt/Window/BackgroundWindowOrderOnSpaceChange.java JBR-6486 macosx-all
jb/java/awt/Window/FullScreenTwoFrames.java JBR-8276 macosx-all
jb/java/awt/Window/ModalDialogAndPopup.java JBR-4984 macosx-all
jb/java/awt/Window/RestoreFromFullScreen.java JBR-7764 linux-all
jb/java/jcef/MouseEventTest.java JBR-4908 linux-all
@@ -1541,5 +1528,3 @@ javax/swing/JSlider/TestJSliderRendering.java JBR-5510 linux-5.18.2-arch1-1
javax/swing/JTextPane/TestJTextPaneBackgroundColor.java JBR-5510 linux-5.18.2-arch1-1
javax/swing/JToolTip/TestTooltipBackgroundColor.java JBR-5510 linux-5.18.2-arch1-1
sun/java2d/ClassCastExceptionForInvalidSurface.java JBR-5510 linux-5.18.2-arch1-1
java/io/File/CheckPermission.java JBR-7700 linux-all,windows-all,macosx-all

View File

@@ -23,6 +23,7 @@ java/awt/Focus/LabelScrollBarFocus.java JBR-6090 windows-x64
java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.java JBR-884,JBR-6090 windows-x64,linux-x64
java/awt/Focus/MouseClickRequestFocusRaceTest/MouseClickRequestFocusRaceTest.java 8194753,JBR-6090 linux-all,macosx-all,windows-x64
java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java 7124275,JBR-5799 macosx-all,windows-all
java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java JBR-7299,JBR-8728 linux-all,windows-all
java/awt/Focus/SimpleWindowActivationTest/SimpleWindowActivationTest.java JBR-6089 windows-all
java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java JBR-6090 windows-all
java/awt/Frame/DynamicLayout/DynamicLayout.java JBR-5799 windows-all
@@ -72,7 +73,7 @@ javax/swing/text/StyledEditorKit/4506788/bug4506788.java JBR-8212 linux-all
jb/java/awt/event/MouseEvent/ReleaseAndClickModifiers.java JBR-6589 windows-all
sanity/client/SwingSet/src/ColorChooserDemoTest.java 8278582,8273312,JBR-8354 windows-all,linux-all
sanity/client/SwingSet/src/GridBagLayoutDemoTest.java JBR-6285,JBR-7473 linux-all,windows-all
sanity/client/SwingSet/src/GridBagLayoutDemoTest.java JBR-6285 linux-all,windows-all
sanity/client/SwingSet/src/InternalFrameDemoTest.java 8253184,JBR-6685 windows-all,linux-all
sanity/client/SwingSet/src/ToolTipDemoTest.java 8293001,JBR-6293 linux-all,windows-all
sun/java2d/GdiRendering/ClipShapeRendering.java JBR-5204 linux-all,macosx-all,windows-all

View File

@@ -12,8 +12,6 @@ javax/swing/JDesktopPane/TestDesktopManagerNPE.java JBR-8449 linux-x64
javax/swing/JEditorPane/JEditorPaneFontFallback.java JBR-8305 linux-all
javax/swing/JFileChooser/6520101/bug6520101.java JBR-7140 linux-all
javax/swing/JFormattedTextField/bug4741926.java JBR-7530 linux-all
javax/swing/JInternalFrame/bug5009724.java JBR-7087 linux-all
javax/swing/JPopupMenu/7156657/bug7156657.java JBR-8210 linux-all
javax/swing/JOptionPane/8081019/bug8081019.java JBR-8275 linux-all
javax/swing/JOptionPane/8081019/bug8081019.java JBR-8275 linux-all
javax/swing/JRadioButton/bug4823809.java JBR-7931 linux-all
@@ -21,7 +19,6 @@ javax/swing/LookAndFeel/8145547/DemandGTK2.sh JBR-8274 linux-all
javax/swing/LookAndFeel/8145547/DemandGTK3.sh JBR-8274 linux-all
javax/swing/text/html/CSS/bug8234913.java JBR-8306 linux-all
javax/swing/text/ParagraphView/6364882/bug6364882.java JBR-8324 linux-all
javax/swing/UI/UnninstallUIMemoryLeaks/UnninstallUIMemoryLeaks.java JBR-8304 linux-all
jb/java/awt/wayland/RobotGetOOBPixelsTest.java JBR-8029 linux-all
jb/java/awt/wayland/RobotGetPixelTest.java JBR-8029 linux-all

View File

@@ -4,5 +4,4 @@ javax/imageio/spi/AppletContextTest/BadPluginConfigurationTest.sh nobug generic-
javax/imageio/plugins/external_plugin_tests/TestClassPathPlugin.sh nobug generic-all # line 59: /opt/teamcity-agent/work/efb45cc305c2e813/jbr/Contents/Home/bin/jar: No such file or directory
javax/swing/JInternalFrame/bug5009724.java JBR-7087 linux-all
javax/swing/JWindow/ShapedAndTranslucentWindows/SetShapeAndClickSwing.java 8013450 macosx-all,windows-all

View File

@@ -26,7 +26,6 @@
* @bug 8164705 8209901
* @library /test/lib
* @summary check jdk.filepermission.canonicalize
* @run main/othervm -Djbr.java.io.use.nio=false Flag
*/
import jdk.test.lib.process.Proc;
@@ -47,7 +46,6 @@ public class Flag {
.prop("java.security.manager", "")
.prop("java.security.policy", policy)
.prop("jdk.io.permissionsUseCanonicalPath", "true")
.prop("jbr.java.io.use.nio", "false")
.args("run", "true", "true")
.start()
.waitFor(0);
@@ -55,7 +53,6 @@ public class Flag {
.prop("java.security.manager", "")
.prop("java.security.policy", policy)
.secprop("jdk.io.permissionsUseCanonicalPath", "true")
.prop("jbr.java.io.use.nio", "false")
.args("run", "true", "true")
.start()
.waitFor(0);
@@ -64,7 +61,6 @@ public class Flag {
.prop("java.security.policy", policy)
.secprop("jdk.io.permissionsUseCanonicalPath", "false")
.prop("jdk.io.permissionsUseCanonicalPath", "true")
.prop("jbr.java.io.use.nio", "false")
.args("run", "true", "true")
.start()
.waitFor(0);
@@ -74,7 +70,6 @@ public class Flag {
.prop("java.security.manager", "")
.prop("java.security.policy", policy)
.prop("jdk.io.permissionsUseCanonicalPath", "false")
.prop("jbr.java.io.use.nio", "false")
.args("run", "false", "true")
.start()
.waitFor(0);
@@ -82,7 +77,6 @@ public class Flag {
.prop("java.security.manager", "")
.prop("java.security.policy", policy)
.secprop("jdk.io.permissionsUseCanonicalPath", "false")
.prop("jbr.java.io.use.nio", "false")
.args("run", "false", "true")
.start()
.waitFor(0);
@@ -91,14 +85,12 @@ public class Flag {
.prop("java.security.policy", policy)
.secprop("jdk.io.permissionsUseCanonicalPath", "true")
.prop("jdk.io.permissionsUseCanonicalPath", "false")
.prop("jbr.java.io.use.nio", "false")
.args("run", "false", "true")
.start()
.waitFor(0);
Proc.create("Flag")
.prop("java.security.manager", "")
.prop("java.security.policy", policy)
.prop("jbr.java.io.use.nio", "false")
.args("run", "false", "true")
.start()
.waitFor(0);