mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 09:29:38 +01:00
Compare commits
5 Commits
kharitonov
...
jb21.0.7-b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a81f16cda5 | ||
|
|
47c1e16883 | ||
|
|
2375d06b37 | ||
|
|
8a62f03e25 | ||
|
|
6c42d04f43 |
@@ -104,6 +104,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
|
||||
|
||||
@@ -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 $?
|
||||
|
||||
@@ -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 $?
|
||||
|
||||
@@ -92,7 +92,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 +119,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=""
|
||||
|
||||
@@ -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<>();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
@@ -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] == '/')))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -815,6 +815,7 @@ jdk_awt_wayland = \
|
||||
-java/awt/Clipboard/LostOwnershipChainTest/SystemClipboardTest.java \
|
||||
-java/awt/ColorClass/AlphaColorTest.java \
|
||||
-java/awt/Component/7097771 \
|
||||
-java/awt/Component/ComponentEventTest.java \
|
||||
-java/awt/Component/ComponentRedrawnTest.java \
|
||||
-java/awt/Component/DimensionEncapsulation \
|
||||
-java/awt/Component/F10TopToplevel \
|
||||
@@ -945,6 +946,7 @@ jdk_awt_wayland = \
|
||||
-java/awt/Focus/InputVerifierTest3 \
|
||||
-java/awt/Focus/KeyEventForBadFocusOwnerTest \
|
||||
-java/awt/Focus/LabelScrollBarFocus.java \
|
||||
-java/awt/MenuShortcut/ActionCommandTest.java \
|
||||
-java/awt/Focus/ModalBlockedStealsFocusTest \
|
||||
-java/awt/Focus/ModalDialogActivationTest \
|
||||
-java/awt/Focus/ModalDialogInFocusEventTest.java \
|
||||
@@ -1094,6 +1096,7 @@ jdk_swing_wayland= \
|
||||
-com/sun/java/swing/plaf/gtk/TestFileChooserCtrlASelection.java \
|
||||
-com/sun/java/swing/plaf/gtk/TestFileChooserSingleDirectorySelection.java \
|
||||
-javax/swing/AbstractButton/6711682/bug6711682.java \
|
||||
-javax/swing/AbstractDocument/bug4549069.java \
|
||||
-javax/swing/Action/8133039/bug8133039.java \
|
||||
-javax/swing/Box/TestBoxFiller.java \
|
||||
-javax/swing/JButton/bug4234034.java \
|
||||
@@ -1287,6 +1290,7 @@ jdk_swing_wayland= \
|
||||
-javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentCanvas.java \
|
||||
-javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentGradient.java \
|
||||
-javax/swing/KeyboardManager/8013370/Test8013370.java \
|
||||
-javax/swing/KeyboardManager/bug4345798.java \
|
||||
-javax/swing/LookAndFeel/8145547/DemandGTK.java \
|
||||
-javax/swing/LookAndFeel/8146276/NimbusGlueTest.java \
|
||||
-javax/swing/LookAndFeel/SystemLookAndFeel/SystemLookAndFeelTest.java \
|
||||
@@ -1342,3 +1346,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
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
// }
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -688,6 +688,7 @@ java/awt/xembed/server/RunTestXEmbed.java 7034201 linux-all
|
||||
java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsDocModalTest.java 8164473 linux-all
|
||||
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/Frame/DisposeTest.java JBR-7937 macosx-aarch64
|
||||
|
||||
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
|
||||
@@ -1022,6 +1023,7 @@ javax/swing/JMenuItem/bug4839464.java JBR-5911 windows-all
|
||||
javax/swing/JMenuItem/6249972/bug6249972.java 8197552 windows-all
|
||||
javax/swing/JOptionPane/7138665/bug7138665.java JBR-5799 windows-all
|
||||
javax/swing/JOptionPane/8081019/bug8081019.java JBR-5767 windows-all
|
||||
javax/swing/JPasswordField/TestSelectedTextBackgroundColor.java JBR-5510,JBR-8665 linux-5.18.2-arch1-1,linux-6.8.0-1017-raspi
|
||||
javax/swing/JProgressBar/8015748/JProgressBarOrientationRobotTest.java JBR-8571 linux-all
|
||||
javax/swing/JPopupMenu/4634626/bug4634626.java 8253184 windows-all
|
||||
javax/swing/JPopupMenu/4760494/bug4760494.java 8253184 windows-all
|
||||
@@ -1126,6 +1128,7 @@ javax/swing/plaf/metal/MetalGradient/8163193/ButtonGradientTest.java 8253184,JBR
|
||||
javax/swing/plaf/synth/7158712/bug7158712.java JBR-125,8322653 linux-all,windows-all,macosx-all
|
||||
javax/swing/plaf/synth/SynthButtonUI/6276188/bug6276188.java 8253184,JBR-5510,JBR-803 windows-all,linux-all,macosx-all
|
||||
javax/swing/plaf/synth/SynthScrollbarThumbPainter/SynthScrollbarThumbPainterTest.java 8253184 windows-all
|
||||
javax/swing/plaf/synth/Test6660049.java JBR-8397 windows-all
|
||||
javax/swing/plaf/synth/Test8043627.java JBR-5767 windows-all
|
||||
javax/swing/JInternalFrame/5066752/bug5066752.java 8253184,JBR-5510 windows-all,linux-5.18.2-arch1-1
|
||||
javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java JBR-5510,JBR-6546 linux-5.18.2-arch1-1,windows-x64
|
||||
@@ -1323,6 +1326,7 @@ java/awt/Focus/RequestFocusByCause/RequestFocusByCauseTest.java JBR-6335 linux-a
|
||||
java/awt/Focus/RequestOnCompWithNullParent/RequestOnCompWithNullParent1.java JBR-6507 linux-all
|
||||
java/awt/Focus/RemoveAfterRequest/RemoveAfterRequest.java JBR-6052 macosx-all,linux-all
|
||||
java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java 8258103,8253184 linux-all,windows-all
|
||||
java/awt/List/HandlingKeyEventIfMousePressedTest.java 6848358 macosx-all,windows-all
|
||||
|
||||
com/sun/jndi/dns/ConfigTests/Timeout.java 8220213 generic-all
|
||||
|
||||
@@ -1391,6 +1395,7 @@ javax/swing/JSpinner/8223788/JSpinnerButtonFocusTest.java JBR-5210 windows-all
|
||||
javax/swing/JSpinner/JSpinnerFocusTest.java JBR-5288 windows-all
|
||||
javax/swing/JSpinner/SpinnerTest.java JBR-4880 windows-all
|
||||
javax/swing/JSpinner/TestJSpinnerFocusLost.java JBR-5210 windows-all
|
||||
javax/swing/JSpinner/TestSelectedTextBackgroundColor.java JBR-5510,JBR-8665 linux-5.18.2-arch1-1,linux-6.8.0-1017-raspi
|
||||
javax/swing/JTable/7068740/bug7068740.java 8197552,JBR-6680 windows-all,linux-all
|
||||
javax/swing/JTable/7124218/SelectEditTableCell.java JBR-6679 linux-all,windows-all
|
||||
javax/swing/JTable/8236907/LastVisibleRow.java JBR-6066 generic-all
|
||||
@@ -1511,7 +1516,7 @@ javax/swing/LookAndFeel/8145547/DemandGTK3.sh JBR-5510 linux-5.18.2-arch1-1
|
||||
jb/java/awt/Focus/BrokenTraversalAWT.java JBR-5799 windows-all
|
||||
jb/java/awt/Focus/ComplexFocusSequence.java JBR-6728 linux-all,windows-x64
|
||||
jb/java/awt/Focus/ContextMenuAfterPopup.java JBR-5799 windows-all
|
||||
jb/java/awt/Focus/FileDialogClosing.java JBR-8309 macosx-x64
|
||||
jb/java/awt/Focus/FileDialogClosing.java JBR-8309 macosx-x64,windows-all
|
||||
jb/java/awt/Focus/FocusTraversalOrderTest.java JBR-6060 generic-all
|
||||
jb/java/awt/Focus/PopupIncomingFocusTest.java JBR-5799 windows-all
|
||||
jb/java/awt/Focus/TitleBarClickTest.java JBR-6394 linux-5.18.2-arch1-1,windows-all
|
||||
@@ -1522,13 +1527,9 @@ java/awt/Choice/ChoiceStaysOpenedOnTAB.java JBR-5510 linux-5.18.2-arch1-1
|
||||
java/awt/Graphics/XORPaint.java#id2 JBR-5510 linux-5.18.2-arch1-1
|
||||
java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java JBR-5510 linux-5.18.2-arch1-1
|
||||
javax/swing/JMenu/TestDisabledMenuForegroundColor.java JBR-5510 linux-5.18.2-arch1-1
|
||||
javax/swing/JPasswordField/TestSelectedTextBackgroundColor.java JBR-5510 linux-5.18.2-arch1-1
|
||||
javax/swing/JProgressBar/TestJProgressBarHighlightColor.java JBR-5510 linux-5.18.2-arch1-1
|
||||
javax/swing/JSlider/TestJSliderRendering.java JBR-5510 linux-5.18.2-arch1-1
|
||||
javax/swing/JSpinner/TestSelectedTextBackgroundColor.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
|
||||
javax/swing/JTree/TestTreeBackgroundColor.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
|
||||
@@ -202,7 +202,7 @@ sun/java2d/pipe/InterpolationQualityTest.java nobug generic-all
|
||||
java/awt/event/ComponentEvent/TextComponentTextEventTest.java JBR-6287 windows-all
|
||||
|
||||
jb/java/awt/Focus/ComplexFocusSequence.java JBR-6728 linux-all,windows-x64
|
||||
jb/java/awt/Focus/FileDialogClosing.java JBR-5799 windows-all
|
||||
jb/java/awt/Focus/FileDialogClosing.java JBR-8309,JBR-5799 macosx-x64,windows-all
|
||||
jb/java/awt/Focus/ModalDialogFromMenuTest.java JBR-5799 windows-all
|
||||
jb/java/awt/Focus/ModalDialogOverSiblingTest.java JBR-5716 windows-all
|
||||
jb/java/awt/Focus/PopupFromMenuTest.java JBR-5799 windows-all
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
java/awt/font/ComplexEmoji.java JBR-5009,JBR-8399 linux-aarch64,linux-x64
|
||||
java/awt/FullScreen/SetFullScreenTest.java JBR-8214,JBR-8400 linux-5.18.2-arch1-1,linux-x64
|
||||
java/awt/MenuShortcut/FunctionKeyShortcut.java JBR-7932 linux-all
|
||||
java/awt/Multiscreen/UpdateGCTest/UpdateGCTest.java JBR-8264 linux-x64
|
||||
|
||||
java/awt/event/KeyEvent/FunctionKeyTest.java JBR-7773 linux-all
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user