mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-22 08:21:48 +01:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47ce5a99a0 | ||
|
|
fed63db5bb | ||
|
|
d136019868 | ||
|
|
80f4e4880c | ||
|
|
8942f83fd4 | ||
|
|
d44fe6c81d | ||
|
|
752e0874ef | ||
|
|
98f483d769 | ||
|
|
8183c5b042 | ||
|
|
4c2ce96b68 | ||
|
|
b715412025 | ||
|
|
0cab753fb1 | ||
|
|
de64e51188 | ||
|
|
03ff99a62b | ||
|
|
18c3fd40ee | ||
|
|
66bd338d23 | ||
|
|
8b0b738416 | ||
|
|
f2a562e0c0 | ||
|
|
fd29e06c9c | ||
|
|
fe55cc7bd9 | ||
|
|
96e0246394 | ||
|
|
4f2900a929 |
@@ -1,10 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euxo pipefail
|
||||
set -euo pipefail
|
||||
|
||||
# This script creates a Docker image suitable for building AArch64 variant
|
||||
|
||||
docker build --platform=linux/aarch64 -t jetbrains/runtime:oraclelinux8_aarch64 -f Dockerfile.oraclelinux .
|
||||
docker build \
|
||||
--platform=linux/aarch64 \
|
||||
-t registry.jetbrains.team/p/jbre/containers/oraclelinux8_aarch64:latest \
|
||||
--no-cache \
|
||||
-f Dockerfile.oraclelinux .
|
||||
|
||||
# NB: the resulting container can (and should) be used without the network
|
||||
# connection (--network none) during build in order to reduce the chance
|
||||
|
||||
@@ -4,7 +4,11 @@ set -euxo pipefail
|
||||
|
||||
# This script creates a Docker image suitable for building musl AArch64 variant
|
||||
|
||||
docker build --platform=linux/aarch64 -t jetbrains/runtime:alpine14_aarch64 -f Dockerfile.alpine .
|
||||
docker build \
|
||||
--platform=linux/aarch64 \
|
||||
-t registry.jetbrains.team/p/jbre/containers/alpine14_aarch64:latest \
|
||||
--no-cache \
|
||||
-f Dockerfile.alpine .
|
||||
|
||||
# NB: the resulting container can (and should) be used without the network
|
||||
# connection (--network none) during build in order to reduce the chance
|
||||
|
||||
@@ -4,7 +4,11 @@ set -euxo pipefail
|
||||
|
||||
# This script creates a Docker image suitable for building musl x64 variant
|
||||
|
||||
docker build --platform=linux/amd64 -t jetbrains/runtime:alpine14_x64 -f Dockerfile.alpine .
|
||||
docker build \
|
||||
--platform=linux/amd64 \
|
||||
-t registry.jetbrains.team/p/jbre/containers/alpine14_x64:latest \
|
||||
--no-cache \
|
||||
-f Dockerfile.alpine .
|
||||
|
||||
# NB: the resulting container can (and should) be used without the network
|
||||
# connection (--network none) during build in order to reduce the chance
|
||||
|
||||
@@ -4,7 +4,13 @@ set -euxo pipefail
|
||||
|
||||
# This script creates a Docker image suitable for building x64 variant
|
||||
|
||||
docker build --platform=linux/amd64 -t jetbrains/runtime:oraclelinux8_x64 -f Dockerfile.oraclelinux .
|
||||
docker build \
|
||||
--platform=linux/amd64 \
|
||||
-t registry.jetbrains.team/p/jbre/containers/oraclelinux8_x64:latest \
|
||||
--no-cache \
|
||||
-f Dockerfile.oraclelinux .
|
||||
|
||||
|
||||
|
||||
# NB: the resulting container can (and should) be used without the network
|
||||
# connection (--network none) during build in order to reduce the chance
|
||||
|
||||
@@ -4,7 +4,11 @@ set -euxo pipefail
|
||||
|
||||
# This script creates a Docker image suitable for building x86 variant
|
||||
|
||||
docker build --platform=linux/i386 -t jetbrains/runtime:ubuntu2004_x86 -f Dockerfile.ubuntu.x86 .
|
||||
docker build \
|
||||
--platform=linux/i386 \
|
||||
-t registry.jetbrains.team/p/jbre/containers/ubuntu2004_x86:latest \
|
||||
--no-cache \
|
||||
-f Dockerfile.ubuntu.x86 .
|
||||
|
||||
# NB: the resulting container can (and should) be used without the network
|
||||
# connection (--network none) during build in order to reduce the chance
|
||||
|
||||
32
src/java.base/share/classes/com/sun/IoOverNio.java
Normal file
32
src/java.base/share/classes/com/sun/IoOverNio.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.sun; // TODO better package
|
||||
|
||||
public class IoOverNio {
|
||||
private IoOverNio() { }
|
||||
|
||||
public static final ThreadLocal<Boolean> ALLOW_IO_OVER_NIO = ThreadLocal.withInitial(() -> true);
|
||||
}
|
||||
@@ -35,7 +35,10 @@ import java.nio.file.Path;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import jdk.internal.util.StaticProperty;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* An abstract representation of file and directory pathnames.
|
||||
@@ -148,11 +151,23 @@ import jdk.internal.util.StaticProperty;
|
||||
public class File
|
||||
implements Serializable, Comparable<File>
|
||||
{
|
||||
static final Supplier<java.nio.file.FileSystem> acquireNioFs;
|
||||
|
||||
/**
|
||||
* The FileSystem object representing the platform's local file system.
|
||||
*/
|
||||
private static final FileSystem FS = DefaultFileSystem.getFileSystem();
|
||||
private static final FileSystem FS;
|
||||
|
||||
static {
|
||||
if (GetPropertyAction.privilegedGetBooleanProp("jbr.java.io.use.nio", true, null)) {
|
||||
IoOverNioFileSystem ioOverNio = new IoOverNioFileSystem(DefaultFileSystem.getFileSystem());
|
||||
FS = ioOverNio;
|
||||
acquireNioFs = ioOverNio::acquireNioFs;
|
||||
} else {
|
||||
FS = DefaultFileSystem.getFileSystem();
|
||||
acquireNioFs = () -> null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This abstract pathname's normalized pathname string. A normalized
|
||||
|
||||
@@ -25,9 +25,16 @@
|
||||
|
||||
package java.io;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import jdk.internal.misc.Blocker;
|
||||
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
import sun.nio.ch.FileChannelImpl;
|
||||
|
||||
@@ -75,6 +82,8 @@ public class FileInputStream extends InputStream
|
||||
|
||||
private volatile boolean closed;
|
||||
|
||||
private final boolean useNio;
|
||||
|
||||
/**
|
||||
* Creates a {@code FileInputStream} by
|
||||
* opening a connection to an actual file,
|
||||
@@ -146,11 +155,42 @@ public class FileInputStream extends InputStream
|
||||
if (file.isInvalid()) {
|
||||
throw new FileNotFoundException("Invalid file path");
|
||||
}
|
||||
fd = new FileDescriptor();
|
||||
fd.attach(this);
|
||||
|
||||
path = name;
|
||||
open(name);
|
||||
FileCleanable.register(fd); // open set the fd, register the cleanup
|
||||
java.nio.file.FileSystem nioFs = File.acquireNioFs.get();
|
||||
useNio = nioFs != null;
|
||||
if (useNio) {
|
||||
Path nioPath = nioFs.getPath(name);
|
||||
if (Files.isDirectory(nioPath)) {
|
||||
throw new FileNotFoundException(name + " is a directory");
|
||||
}
|
||||
try {
|
||||
// NB: the channel will be closed in the close() method
|
||||
// TODO Handle UnsupportedOperationException from newFileChannel
|
||||
var ch = nioFs.provider().newFileChannel(nioPath, Set.of(StandardOpenOption.READ));
|
||||
channel = ch;
|
||||
if (ch instanceof FileChannelImpl fci) {
|
||||
fci.setUninterruptible();
|
||||
fd = fci.getFD(); // TODO: this is a temporary workaround
|
||||
fd.attach(this);
|
||||
FileCleanable.register(fd);
|
||||
} else {
|
||||
fd = new FileDescriptor();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (IoOverNioFileSystem.DEBUG) {
|
||||
new Throwable(String.format("Can't create a FileInputStream for %s with %s", file, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
// Since we can't throw IOException...
|
||||
throw new FileNotFoundException(e.getMessage());
|
||||
}
|
||||
} else {
|
||||
fd = new FileDescriptor();
|
||||
fd.attach(this);
|
||||
open(name);
|
||||
FileCleanable.register(fd); // open set the fd, register the cleanup
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,6 +218,8 @@ public class FileInputStream extends InputStream
|
||||
* @see SecurityManager#checkRead(java.io.FileDescriptor)
|
||||
*/
|
||||
public FileInputStream(FileDescriptor fdObj) {
|
||||
useNio = false;
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (fdObj == null) {
|
||||
@@ -228,7 +270,7 @@ public class FileInputStream extends InputStream
|
||||
public int read() throws IOException {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
return read0();
|
||||
return implRead();
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
@@ -236,6 +278,16 @@ public class FileInputStream extends InputStream
|
||||
|
||||
private native int read0() throws IOException;
|
||||
|
||||
private int implRead() throws IOException {
|
||||
if (useNio) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1);
|
||||
int nRead = getChannel().read(buffer);
|
||||
buffer.rewind();
|
||||
return nRead == 1 ? (buffer.get() & 0xFF) : -1;
|
||||
}
|
||||
return read0();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a subarray as a sequence of bytes.
|
||||
* @param b the data to be written
|
||||
@@ -260,12 +312,25 @@ public class FileInputStream extends InputStream
|
||||
public int read(byte[] b) throws IOException {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
return readBytes(b, 0, b.length);
|
||||
return implRead(b);
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
}
|
||||
|
||||
private int implRead(byte[] b) throws IOException {
|
||||
if (useNio) {
|
||||
try {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(b);
|
||||
return getChannel().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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -284,12 +349,25 @@ public class FileInputStream extends InputStream
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
return readBytes(b, off, len);
|
||||
return implRead(b, off, len);
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
}
|
||||
|
||||
private int implRead(byte[] b, int off, int len) throws IOException {
|
||||
if (useNio) {
|
||||
try {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
|
||||
return getChannel().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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] readAllBytes() throws IOException {
|
||||
long length = length();
|
||||
@@ -396,6 +474,9 @@ public class FileInputStream extends InputStream
|
||||
private long length() throws IOException {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
if (useNio) {
|
||||
return getChannel().size();
|
||||
}
|
||||
return length0();
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
@@ -406,6 +487,9 @@ public class FileInputStream extends InputStream
|
||||
private long position() throws IOException {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
if (useNio) {
|
||||
return getChannel().position();
|
||||
}
|
||||
return position0();
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
@@ -441,6 +525,12 @@ public class FileInputStream extends InputStream
|
||||
public long skip(long n) throws IOException {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
if (useNio) {
|
||||
getChannel();
|
||||
long startPos = channel.position();
|
||||
channel.position(startPos + n);
|
||||
return channel.position() - startPos;
|
||||
}
|
||||
return skip0(n);
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
@@ -470,7 +560,15 @@ public class FileInputStream extends InputStream
|
||||
public int available() throws IOException {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
return available0();
|
||||
if (!useNio || path == null) {
|
||||
return available0();
|
||||
} else {
|
||||
FileChannel channel = getChannel();
|
||||
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;
|
||||
}
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,14 @@
|
||||
|
||||
package java.io;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Set;
|
||||
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.access.JavaIOFileDescriptorAccess;
|
||||
import jdk.internal.misc.Blocker;
|
||||
@@ -89,6 +96,8 @@ public class FileOutputStream extends OutputStream
|
||||
|
||||
private volatile boolean closed;
|
||||
|
||||
private final boolean useNio;
|
||||
|
||||
/**
|
||||
* Creates a file output stream to write to the file with the
|
||||
* specified name. A new {@code FileDescriptor} object is
|
||||
@@ -223,12 +232,45 @@ public class FileOutputStream extends OutputStream
|
||||
if (file.isInvalid()) {
|
||||
throw new FileNotFoundException("Invalid file path");
|
||||
}
|
||||
this.fd = new FileDescriptor();
|
||||
fd.attach(this);
|
||||
this.path = name;
|
||||
|
||||
open(name, append);
|
||||
FileCleanable.register(fd); // open sets the fd, register the cleanup
|
||||
this.path = name;
|
||||
java.nio.file.FileSystem nioFs = File.acquireNioFs.get();
|
||||
useNio = nioFs != null;
|
||||
if (useNio) {
|
||||
Path nioPath = nioFs.getPath(name);
|
||||
if (Files.isDirectory(nioPath)) {
|
||||
throw new FileNotFoundException(name + " is a directory");
|
||||
}
|
||||
try {
|
||||
// NB: the channel will be closed in the close() method
|
||||
// TODO Handle UOE
|
||||
var ch = FileSystems.getDefault().provider().newFileChannel(
|
||||
nioPath,
|
||||
append ? Set.of(StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND)
|
||||
: Set.of(StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING));
|
||||
channel = ch;
|
||||
if (ch instanceof FileChannelImpl fci) {
|
||||
fci.setUninterruptible();
|
||||
fd = fci.getFD(); // TODO: this is a temporary workaround
|
||||
fd.attach(this);
|
||||
FileCleanable.register(fd);
|
||||
} else {
|
||||
fd = new FileDescriptor();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (IoOverNioFileSystem.DEBUG) {
|
||||
new Throwable(String.format("Can't create a FileOutputStream for %s with %s", file, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
// Since we can't throw IOException...
|
||||
throw new FileNotFoundException(e.getMessage());
|
||||
}
|
||||
} else {
|
||||
this.fd = new FileDescriptor();
|
||||
fd.attach(this);
|
||||
open(name, append);
|
||||
FileCleanable.register(fd); // open sets the fd, register the cleanup
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,6 +297,8 @@ public class FileOutputStream extends OutputStream
|
||||
* @see java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)
|
||||
*/
|
||||
public FileOutputStream(FileDescriptor fdObj) {
|
||||
useNio = false;
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (fdObj == null) {
|
||||
@@ -313,12 +357,24 @@ public class FileOutputStream extends OutputStream
|
||||
boolean append = FD_ACCESS.getAppend(fd);
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
write(b, append);
|
||||
implWrite(b, append);
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
}
|
||||
|
||||
private void implWrite(int b, boolean append) throws IOException {
|
||||
if (useNio) {
|
||||
// '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);
|
||||
getChannel().write(buffer);
|
||||
} else {
|
||||
write(b, append);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a sub array as a sequence of bytes.
|
||||
* @param b the data to be written
|
||||
@@ -343,7 +399,7 @@ public class FileOutputStream extends OutputStream
|
||||
boolean append = FD_ACCESS.getAppend(fd);
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
writeBytes(b, 0, b.length, append);
|
||||
implWriteBytes(b, 0, b.length, append);
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
@@ -364,12 +420,27 @@ public class FileOutputStream extends OutputStream
|
||||
boolean append = FD_ACCESS.getAppend(fd);
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
writeBytes(b, off, len, append);
|
||||
implWriteBytes(b, off, len, append);
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
}
|
||||
|
||||
private void implWriteBytes(byte[] b, int off, int len, boolean append) throws IOException {
|
||||
if (useNio) {
|
||||
// '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);
|
||||
getChannel().write(buffer);
|
||||
} catch (OutOfMemoryError e) {
|
||||
// May fail to allocate direct buffer memory due to small -XX:MaxDirectMemorySize
|
||||
writeBytes(b, off, len, append);
|
||||
}
|
||||
} else {
|
||||
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
|
||||
|
||||
665
src/java.base/share/classes/java/io/IoOverNioFileSystem.java
Normal file
665
src/java.base/share/classes/java/io/IoOverNioFileSystem.java
Normal file
@@ -0,0 +1,665 @@
|
||||
/*
|
||||
* 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 com.sun.IoOverNio;
|
||||
import jdk.internal.misc.VM;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.util.*;
|
||||
|
||||
class IoOverNioFileSystem extends FileSystem {
|
||||
static final boolean DEBUG = GetPropertyAction.privilegedGetBooleanProp("jbr.java.io.use.nio.debug", false, null);
|
||||
private final FileSystem defaultFileSystem;
|
||||
|
||||
IoOverNioFileSystem(FileSystem defaultFileSystem) {
|
||||
this.defaultFileSystem = defaultFileSystem;
|
||||
}
|
||||
|
||||
java.nio.file.FileSystem acquireNioFs() {
|
||||
if (!VM.isBooted()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!IoOverNio.ALLOW_IO_OVER_NIO.get()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return FileSystems.getDefault();
|
||||
} catch (NullPointerException ignored) {
|
||||
// TODO Explain.
|
||||
// TODO Probably, it can be removed now.
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean setPermission0(java.nio.file.FileSystem nioFs, File f, int access, boolean enable, boolean owneronly) {
|
||||
Path path;
|
||||
try {
|
||||
path = nioFs.getPath(f.getPath());
|
||||
} catch (InvalidPathException err) {
|
||||
throw new InternalError(err.getMessage(), err);
|
||||
}
|
||||
|
||||
// See the comment inside getBooleanAttributes that explains the order of file attribute view classes.
|
||||
BasicFileAttributeView view;
|
||||
try {
|
||||
view = Files.getFileAttributeView(path, PosixFileAttributeView.class);
|
||||
} catch (UnsupportedOperationException ignored) {
|
||||
view = null;
|
||||
}
|
||||
if (view == null) {
|
||||
try {
|
||||
view = Files.getFileAttributeView(path, DosFileAttributeView.class);
|
||||
} catch (UnsupportedOperationException err) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("File system %s supports neither posix nor dos attributes", nioFs), err)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean result = true;
|
||||
if (view instanceof DosFileAttributeView dosView) {
|
||||
if (((access & ACCESS_READ) != 0)) {
|
||||
try {
|
||||
dosView.setReadOnly(enable);
|
||||
} catch (IOException e) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't set read only attributes for %s with %s", f, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
} else if (view instanceof PosixFileAttributeView posixView) {
|
||||
try {
|
||||
Set<PosixFilePermission> perms = posixView.readAttributes().permissions();
|
||||
|
||||
if ((access & ACCESS_READ) != 0) {
|
||||
if (enable) {
|
||||
perms.add(PosixFilePermission.OWNER_READ);
|
||||
} else {
|
||||
perms.remove(PosixFilePermission.OWNER_READ);
|
||||
}
|
||||
if (!owneronly) {
|
||||
if (enable) {
|
||||
perms.add(PosixFilePermission.GROUP_READ);
|
||||
perms.add(PosixFilePermission.OTHERS_READ);
|
||||
} else {
|
||||
perms.remove(PosixFilePermission.GROUP_READ);
|
||||
perms.remove(PosixFilePermission.OTHERS_READ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((access & ACCESS_WRITE) != 0) {
|
||||
if (enable) {
|
||||
perms.add(PosixFilePermission.OWNER_WRITE);
|
||||
} else {
|
||||
perms.remove(PosixFilePermission.OWNER_WRITE);
|
||||
}
|
||||
if (!owneronly) {
|
||||
if (enable) {
|
||||
perms.add(PosixFilePermission.GROUP_WRITE);
|
||||
perms.add(PosixFilePermission.OTHERS_WRITE);
|
||||
} else {
|
||||
perms.remove(PosixFilePermission.GROUP_WRITE);
|
||||
perms.remove(PosixFilePermission.OTHERS_WRITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((access & ACCESS_EXECUTE) != 0) {
|
||||
if (enable) {
|
||||
perms.add(PosixFilePermission.OWNER_EXECUTE);
|
||||
} else {
|
||||
perms.remove(PosixFilePermission.OWNER_EXECUTE);
|
||||
}
|
||||
if (!owneronly) {
|
||||
if (enable) {
|
||||
perms.add(PosixFilePermission.GROUP_EXECUTE);
|
||||
perms.add(PosixFilePermission.OTHERS_EXECUTE);
|
||||
} else {
|
||||
perms.remove(PosixFilePermission.GROUP_EXECUTE);
|
||||
perms.remove(PosixFilePermission.OTHERS_EXECUTE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
posixView.setPermissions(perms);
|
||||
} catch (IOException e) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't set posix attributes for %s with %s", f, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getSeparator() {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
return nioFs.getSeparator().charAt(0);
|
||||
}
|
||||
return defaultFileSystem.getSeparator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getPathSeparator() {
|
||||
return defaultFileSystem.getPathSeparator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String normalize(String path) {
|
||||
// java.nio.file.Path.normalize works differently compared to this normalizer.
|
||||
// Especially, Path.normalize converts "." into an empty string, which breaks
|
||||
// even tests in OpenJDK.
|
||||
return defaultFileSystem.normalize(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int prefixLength(String path) {
|
||||
// Although it's possible to represent this function via `Path.getRoot`,
|
||||
// the default file system and java.nio handle corner cases with incorrect paths differently.
|
||||
return defaultFileSystem.prefixLength(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolve(String parent, String child) {
|
||||
// java.nio is stricter to various invalid symbols than java.io.
|
||||
return defaultFileSystem.resolve(parent, child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultParent() {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
return nioFs.getSeparator();
|
||||
}
|
||||
return defaultFileSystem.getDefaultParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fromURIPath(String path) {
|
||||
return defaultFileSystem.fromURIPath(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAbsolute(File f) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
return nioFs.getPath(f.getPath()).isAbsolute();
|
||||
} catch (InvalidPathException err) {
|
||||
// Path parsing in java.nio is stricter than in java.io.
|
||||
// Giving a chance to the original implementation.
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't check if a path is absolute with %s", nioFs), err)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.isAbsolute(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInvalid(File f) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
Path ignored = nioFs.getPath(f.getPath());
|
||||
return false;
|
||||
} catch (InvalidPathException ignored) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.isInvalid(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolve(File f) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
return nioFs.getPath(f.getPath()).toAbsolutePath().toString();
|
||||
} catch (InvalidPathException err) {
|
||||
// Path parsing in java.nio is stricter than in java.io.
|
||||
// Giving a chance to the original implementation.
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't resolve a path with %s", nioFs), err)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.resolve(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String canonicalize(String path) throws IOException {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
IOException firstErr = null;
|
||||
Path nioPath = nioFs.getPath(path);
|
||||
Path suffix = nioFs.getPath("");
|
||||
|
||||
do {
|
||||
try {
|
||||
return nioPath.toRealPath().resolve(suffix).toString();
|
||||
} catch (IOException err) {
|
||||
if (firstErr == null) {
|
||||
firstErr = err;
|
||||
}
|
||||
}
|
||||
|
||||
suffix = nioPath.getFileName().resolve(suffix);
|
||||
nioPath = nioPath.getParent();
|
||||
} while (nioPath != null);
|
||||
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't canonicalize a path %s with %s", path, nioFs), firstErr)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
|
||||
throw firstErr;
|
||||
} catch (InvalidPathException err) {
|
||||
// Path parsing in java.nio is stricter than in java.io.
|
||||
// Giving a chance to the original implementation.
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't canonicalize a path %s with %s", path, nioFs), err)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.canonicalize(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBooleanAttributes(File f) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
Path path = nioFs.getPath(f.getPath());
|
||||
|
||||
// The order of checking Posix attributes first and DOS attributes next is deliberate.
|
||||
// WindowsFileSystem supports these attributes: basic, dos, acl, owner, user.
|
||||
// LinuxFileSystem supports: basic, posix, unix, owner, dos, user.
|
||||
// MacOSFileSystem and BsdFileSystem support: basic, posix, unix, owner, user.
|
||||
//
|
||||
// Notice that Linux FS supports DOS attributes, which is unexpected.
|
||||
// The DOS adapter implementation from LinuxFileSystem uses `open` for getting attributes.
|
||||
// It's not only more expensive than `stat`, but also doesn't work with Unix sockets.
|
||||
//
|
||||
// Also, notice that Windows FS does not support Posix attributes, which is expected.
|
||||
// Checking for Posix attributes allows filtering Windows out,
|
||||
// even though Posix permissions aren't used in this method.
|
||||
BasicFileAttributes attrs;
|
||||
try {
|
||||
attrs = Files.readAttributes(path, PosixFileAttributes.class);
|
||||
} catch (UnsupportedOperationException ignored) {
|
||||
attrs = Files.readAttributes(path, DosFileAttributes.class);
|
||||
}
|
||||
|
||||
return BA_EXISTS
|
||||
| (attrs.isDirectory() ? BA_DIRECTORY : 0)
|
||||
| (attrs.isRegularFile() ? BA_REGULAR : 0)
|
||||
| (attrs instanceof DosFileAttributes dosAttrs && dosAttrs.isHidden() ? BA_HIDDEN : 0);
|
||||
} catch (InvalidPathException err) {
|
||||
// Path parsing in java.nio is stricter than in java.io.
|
||||
// Giving a chance to the original implementation.
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't get attributes for a path with %s", nioFs), err)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't get attributes a path %s with %s", f, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.getBooleanAttributes(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkAccess(File f, int access) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
Path path = nioFs.getPath(f.getPath());
|
||||
|
||||
int i = 0;
|
||||
AccessMode[] accessMode = new AccessMode[3];
|
||||
if ((access & ACCESS_READ) != 0) {
|
||||
accessMode[i++] = AccessMode.READ;
|
||||
}
|
||||
if ((access & ACCESS_WRITE) != 0) {
|
||||
accessMode[i++] = AccessMode.WRITE;
|
||||
}
|
||||
if ((access & ACCESS_EXECUTE) != 0) {
|
||||
accessMode[i++] = AccessMode.EXECUTE;
|
||||
}
|
||||
accessMode = Arrays.copyOf(accessMode, i);
|
||||
|
||||
nioFs.provider().checkAccess(path, accessMode);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't check access for a path %s with %s", f, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
return false;
|
||||
} catch (InvalidPathException err) {
|
||||
throw new InternalError(err.getMessage(), err);
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.checkAccess(f, access);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setPermission(File f, int access, boolean enable, boolean owneronly) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
return setPermission0(nioFs, f, access, enable, owneronly);
|
||||
}
|
||||
return defaultFileSystem.setPermission(f, access, enable, owneronly);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastModifiedTime(File f) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
Path path = nioFs.getPath(f.getPath());
|
||||
nioFs.provider().readAttributes(path, BasicFileAttributes.class).lastModifiedTime();
|
||||
} catch (IOException err) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't get last modified time for a path %s with %s", f, nioFs), err)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
return 0;
|
||||
} catch (InvalidPathException err) {
|
||||
throw new InternalError(err.getMessage(), err);
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.getLastModifiedTime(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength(File f) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
try {
|
||||
if (nioFs != null) {
|
||||
Path path = nioFs.getPath(f.getPath());
|
||||
return nioFs.provider().readAttributes(path, BasicFileAttributes.class).size();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't get file length for a path %s with %s", f, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
return 0;
|
||||
} catch (InvalidPathException e) {
|
||||
throw new InternalError(e.getMessage(), e);
|
||||
}
|
||||
return defaultFileSystem.getLength(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createFileExclusively(String pathname) throws IOException {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
try {
|
||||
if (nioFs != null) {
|
||||
Path path = nioFs.getPath(pathname);
|
||||
nioFs.provider().newByteChannel(
|
||||
path,
|
||||
EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)
|
||||
).close();
|
||||
return true;
|
||||
}
|
||||
} catch (FileAlreadyExistsException e) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't exclusively create a file %s with %s", pathname, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
return false;
|
||||
} catch (InvalidPathException e) {
|
||||
throw new IOException(e.getMessage(), e); // The default file system would throw IOException too.
|
||||
}
|
||||
return defaultFileSystem.createFileExclusively(pathname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(File f) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
Path path = nioFs.getPath(f.getPath());
|
||||
nioFs.provider().delete(path);
|
||||
return true;
|
||||
} catch (InvalidPathException e) {
|
||||
throw new InternalError(e.getMessage(), e);
|
||||
} catch (IOException e) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't delete a path %s with %s", f, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.delete(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] list(File f) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
Path path = nioFs.getPath(f.getPath());
|
||||
try (DirectoryStream<Path> children = nioFs.provider().newDirectoryStream(path, AcceptAllFilter.FILTER)) {
|
||||
List<String> result = new ArrayList<>();
|
||||
for (Path child : children) {
|
||||
result.add(child.getFileName().toString());
|
||||
}
|
||||
return result.toArray(String[]::new);
|
||||
}
|
||||
} catch (InvalidPathException e) {
|
||||
throw new InternalError(e.getMessage(), e);
|
||||
} catch (IOException e) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't list a path %s with %s", f, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.list(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createDirectory(File f) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
Path path = nioFs.getPath(f.getPath());
|
||||
nioFs.provider().createDirectory(path);
|
||||
return true;
|
||||
} catch (InvalidPathException e) {
|
||||
throw new InternalError(e.getMessage(), e);
|
||||
} catch (IOException e) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't create a directory %s with %s", f, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.createDirectory(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean rename(File f1, File f2) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
Path path1 = nioFs.getPath(f1.getPath());
|
||||
Path path2 = nioFs.getPath(f2.getPath());
|
||||
nioFs.provider().move(path1, path2, StandardCopyOption.REPLACE_EXISTING);
|
||||
return true;
|
||||
} catch (InvalidPathException e) {
|
||||
throw new InternalError(e.getMessage(), e);
|
||||
} catch (IOException e) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't rename %s to %s with %s", f1, f2, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.rename(f1, f2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setLastModifiedTime(File f, long time) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
Path path = nioFs.getPath(f.getPath());
|
||||
nioFs.provider()
|
||||
.getFileAttributeView(path, BasicFileAttributeView.class)
|
||||
.setTimes(FileTime.fromMillis(time), null, null);
|
||||
return true;
|
||||
} catch (InvalidPathException e) {
|
||||
throw new InternalError(e.getMessage(), e);
|
||||
} catch (IOException e) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't set last modified time of %s with %s", f, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.setLastModifiedTime(f, time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setReadOnly(File f) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
return setPermission0(nioFs, f, ACCESS_EXECUTE | ACCESS_WRITE, false, false);
|
||||
}
|
||||
return defaultFileSystem.setReadOnly(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File[] listRoots() {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
List<File> roots = new ArrayList<>();
|
||||
for (Path rootDirectory : nioFs.getRootDirectories()) {
|
||||
roots.add(rootDirectory.toFile());
|
||||
}
|
||||
return roots.toArray(File[]::new);
|
||||
}
|
||||
return defaultFileSystem.listRoots();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSpace(File f, int t) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
Path path = nioFs.getPath(f.getPath());
|
||||
FileStore store = nioFs.provider().getFileStore(path);
|
||||
return switch (t) {
|
||||
case SPACE_TOTAL -> store.getTotalSpace();
|
||||
case SPACE_USABLE -> store.getUsableSpace();
|
||||
case SPACE_FREE -> store.getUnallocatedSpace();
|
||||
default -> throw new IllegalArgumentException("Invalid space type: " + t);
|
||||
};
|
||||
} catch (InvalidPathException e) {
|
||||
throw new InternalError(e.getMessage(), e);
|
||||
} catch (IOException e) {
|
||||
if (DEBUG) {
|
||||
new Throwable(String.format("Can't get space %s for a path %s with %s", t, f, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.getSpace(f, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNameMax(String path) {
|
||||
// TODO Seems to be impossible with java.nio.
|
||||
return defaultFileSystem.getNameMax(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(File f1, File f2) {
|
||||
java.nio.file.FileSystem nioFs = acquireNioFs();
|
||||
if (nioFs != null) {
|
||||
try {
|
||||
Path p1 = nioFs.getPath(f1.getPath());
|
||||
Path p2 = nioFs.getPath(f2.getPath());
|
||||
return p1.compareTo(p2);
|
||||
} catch (InvalidPathException e) {
|
||||
// Path parsing in java.nio is stricter than in java.io.
|
||||
// Giving a chance to the original implementation.
|
||||
}
|
||||
}
|
||||
return defaultFileSystem.compare(f1, f2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode(File f) {
|
||||
return defaultFileSystem.hashCode(f);
|
||||
}
|
||||
|
||||
private static class AcceptAllFilter implements DirectoryStream.Filter<Path> {
|
||||
static final AcceptAllFilter FILTER = new AcceptAllFilter();
|
||||
|
||||
private AcceptAllFilter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(Path entry) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,14 @@
|
||||
|
||||
package java.io;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
import jdk.internal.access.JavaIORandomAccessFileAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
@@ -90,6 +97,8 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
private volatile FileChannel channel;
|
||||
private volatile boolean closed;
|
||||
|
||||
private final boolean useNio;
|
||||
|
||||
/**
|
||||
* Creates a random access file stream to read from, and optionally
|
||||
* to write to, a file with the specified name. A new
|
||||
@@ -267,11 +276,55 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
if (file.isInvalid()) {
|
||||
throw new FileNotFoundException("Invalid file path");
|
||||
}
|
||||
fd = new FileDescriptor();
|
||||
fd.attach(this);
|
||||
path = name;
|
||||
open(name, imode);
|
||||
FileCleanable.register(fd); // open sets the fd, register the cleanup
|
||||
FileSystem nioFs = File.acquireNioFs.get();
|
||||
useNio = nioFs != null;
|
||||
if (useNio) {
|
||||
Path nioPath = nioFs.getPath(name);
|
||||
if (Files.isDirectory(nioPath)) {
|
||||
throw new FileNotFoundException(name + " is a directory");
|
||||
}
|
||||
try {
|
||||
var options = optionsForChannel(imode);
|
||||
// NB: the channel will be closed in the close() method
|
||||
// TODO Handle UOE
|
||||
var ch = nioFs.provider().newFileChannel(nioPath, options);
|
||||
channel = ch;
|
||||
if (ch instanceof FileChannelImpl fci) {
|
||||
fci.setUninterruptible();
|
||||
fd = fci.getFD(); // TODO: this is a temporary workaround
|
||||
fd.attach(this);
|
||||
FileCleanable.register(fd);
|
||||
} else {
|
||||
fd = new FileDescriptor();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (IoOverNioFileSystem.DEBUG) {
|
||||
new Throwable(String.format("Can't create a RandomAccessFile for %s with %s", file, nioFs), e)
|
||||
.printStackTrace(System.err);
|
||||
}
|
||||
// Since we can't throw IOException...
|
||||
throw new FileNotFoundException(e.getMessage());
|
||||
}
|
||||
} else {
|
||||
fd = new FileDescriptor();
|
||||
fd.attach(this);
|
||||
open(name, imode);
|
||||
FileCleanable.register(fd); // open sets the fd, register the cleanup
|
||||
}
|
||||
}
|
||||
|
||||
private static HashSet<StandardOpenOption> optionsForChannel(int imode) {
|
||||
HashSet<StandardOpenOption> 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);
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -379,12 +432,24 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
public int read() throws IOException {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
return read0();
|
||||
return implRead();
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
}
|
||||
|
||||
private int implRead() throws IOException {
|
||||
if (useNio) {
|
||||
// Really same to FileInputStream.read()
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1);
|
||||
int nRead = getChannel().read(buffer);
|
||||
buffer.rewind();
|
||||
return nRead == 1 ? (buffer.get() & 0xFF) : -1;
|
||||
} else {
|
||||
return read0();
|
||||
}
|
||||
}
|
||||
|
||||
private native int read0() throws IOException;
|
||||
|
||||
/**
|
||||
@@ -397,12 +462,26 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
private int readBytes(byte[] b, int off, int len) throws IOException {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
return readBytes0(b, off, len);
|
||||
return implReadBytes(b, off, len);
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
}
|
||||
|
||||
private int implReadBytes(byte[] b, int off, int len) throws IOException {
|
||||
if (useNio) {
|
||||
try {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
|
||||
return getChannel().read(buffer);
|
||||
} catch (OutOfMemoryError e) {
|
||||
// May fail to allocate direct buffer memory due to small -XX:MaxDirectMemorySize
|
||||
return readBytes0(b, off, len);
|
||||
}
|
||||
} else {
|
||||
return readBytes0(b, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
private native int readBytes0(byte[] b, int off, int len) throws IOException;
|
||||
|
||||
/**
|
||||
@@ -431,7 +510,17 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
* {@code b.length - off}
|
||||
*/
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
return readBytes(b, off, len);
|
||||
if (useNio) {
|
||||
try {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
|
||||
return getChannel().read(buffer);
|
||||
} catch (OutOfMemoryError e) {
|
||||
// May fail to allocate direct buffer memory due to small -XX:MaxDirectMemorySize
|
||||
return readBytes(b, off, len);
|
||||
}
|
||||
} else {
|
||||
return readBytes(b, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -454,7 +543,17 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
* @throws NullPointerException If {@code b} is {@code null}.
|
||||
*/
|
||||
public int read(byte[] b) throws IOException {
|
||||
return readBytes(b, 0, b.length);
|
||||
if (useNio) {
|
||||
try {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(b);
|
||||
return getChannel().read(buffer);
|
||||
} catch (OutOfMemoryError e) {
|
||||
// May fail to allocate direct buffer memory due to small -XX:MaxDirectMemorySize
|
||||
return readBytes(b, 0, b.length);
|
||||
}
|
||||
} else {
|
||||
return readBytes(b, 0, b.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -550,12 +649,23 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
public void write(int b) throws IOException {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
write0(b);
|
||||
implWrite(b);
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
}
|
||||
|
||||
private void implWrite(int b) throws IOException {
|
||||
if (useNio) {
|
||||
byte[] array = new byte[1];
|
||||
array[0] = (byte) b;
|
||||
ByteBuffer buffer = ByteBuffer.wrap(array);
|
||||
getChannel().write(buffer);
|
||||
} else {
|
||||
write0(b);
|
||||
}
|
||||
}
|
||||
|
||||
private native void write0(int b) throws IOException;
|
||||
|
||||
/**
|
||||
@@ -569,12 +679,26 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
private void writeBytes(byte[] b, int off, int len) throws IOException {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
writeBytes0(b, off, len);
|
||||
implWriteBytes(b, off, len);
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
}
|
||||
|
||||
private void implWriteBytes(byte[] b, int off, int len) throws IOException {
|
||||
if (useNio) {
|
||||
try {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(b, off, len);
|
||||
getChannel().write(buffer);
|
||||
} catch (OutOfMemoryError e) {
|
||||
// May fail to allocate direct buffer memory due to small -XX:MaxDirectMemorySize
|
||||
writeBytes0(b, off, len);
|
||||
}
|
||||
} else {
|
||||
writeBytes0(b, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
private native void writeBytes0(byte[] b, int off, int len) throws IOException;
|
||||
|
||||
/**
|
||||
@@ -611,7 +735,15 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
* at which the next read or write occurs.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public native long getFilePointer() throws IOException;
|
||||
public long getFilePointer() throws IOException {
|
||||
if (useNio) {
|
||||
return getChannel().position();
|
||||
} else {
|
||||
return getFilePointer0();
|
||||
}
|
||||
}
|
||||
|
||||
private native long getFilePointer0() throws IOException;
|
||||
|
||||
/**
|
||||
* Sets the file-pointer offset, measured from the beginning of this
|
||||
@@ -633,7 +765,11 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
}
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
seek0(pos);
|
||||
if (useNio) {
|
||||
getChannel().position(pos);
|
||||
} else {
|
||||
seek0(pos);
|
||||
}
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
@@ -650,7 +786,11 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
public long length() throws IOException {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
return length0();
|
||||
if (useNio) {
|
||||
return getChannel().size();
|
||||
} else {
|
||||
return length0();
|
||||
}
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
@@ -680,7 +820,26 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
|
||||
public void setLength(long newLength) throws IOException {
|
||||
long comp = Blocker.begin();
|
||||
try {
|
||||
setLength0(newLength);
|
||||
if (useNio) {
|
||||
FileChannel channel = getChannel();
|
||||
long oldSize = channel.size();
|
||||
if (newLength < oldSize) {
|
||||
channel.truncate(newLength);
|
||||
} else {
|
||||
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);
|
||||
channel.write(buffer);
|
||||
remains -= length;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setLength0(newLength);
|
||||
}
|
||||
} finally {
|
||||
Blocker.end(comp);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.CodeSource;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -2335,6 +2336,16 @@ public final class System {
|
||||
// set TCCL
|
||||
Thread.currentThread().setContextClassLoader(scl);
|
||||
|
||||
if (Boolean.getBoolean("java.util.zip.use.nio.for.zip.file.access")
|
||||
&& System.getProperty("java.nio.file.spi.DefaultFileSystemProvider") != null) {
|
||||
// Make sure the custom file system(s) are loaded using the "standard" ZipFile operating mode
|
||||
// rather than the one that forwards to NIO. The latter will use the file system that is being loaded to
|
||||
// try to load files, which will result in an NPE from FileSystems.getDefault().
|
||||
// Calling FileSystems.getDefault() here bypasses that because the NIO operating mode of ZipFile only
|
||||
// activates at init level 4.
|
||||
FileSystems.getDefault();
|
||||
}
|
||||
|
||||
// system is fully initialized
|
||||
VM.initLevel(4);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.util.Map;
|
||||
import java.util.ServiceConfigurationError;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import jdk.internal.loader.ClassLoaders;
|
||||
import jdk.internal.misc.VM;
|
||||
import sun.nio.fs.DefaultFileSystemProvider;
|
||||
|
||||
@@ -120,11 +121,9 @@ public final class FileSystems {
|
||||
if (propValue != null) {
|
||||
for (String cn: propValue.split(",")) {
|
||||
try {
|
||||
Class<?> c = Class
|
||||
.forName(cn, true, ClassLoader.getSystemClassLoader());
|
||||
Constructor<?> ctor = c
|
||||
.getDeclaredConstructor(FileSystemProvider.class);
|
||||
provider = (FileSystemProvider)ctor.newInstance(provider);
|
||||
Class<?> c = Class.forName(cn, true, ClassLoaders.appClassLoader());
|
||||
Constructor<?> ctor = c.getDeclaredConstructor(FileSystemProvider.class);
|
||||
provider = (FileSystemProvider) ctor.newInstance(provider);
|
||||
|
||||
// must be "file"
|
||||
if (!provider.getScheme().equals("file"))
|
||||
@@ -154,13 +153,17 @@ public final class FileSystems {
|
||||
* is invoked to create the default file system.
|
||||
*
|
||||
* <p> If the system property {@code java.nio.file.spi.DefaultFileSystemProvider}
|
||||
* is defined then it is taken to be a list of one or more fully-qualified
|
||||
* names of concrete provider classes identified by the URI scheme
|
||||
* {@code "file"}. Where the property is a list of more than one name then
|
||||
* the names are separated by a comma. Each class is loaded, using the system
|
||||
* class loader, and instantiated by invoking a one argument constructor
|
||||
* whose formal parameter type is {@code FileSystemProvider}. The providers
|
||||
* are loaded and instantiated in the order they are listed in the property.
|
||||
* is defined then it is taken to be a list of one or more fully-qualified names
|
||||
* of concrete provider classes identified by the URI scheme {@code "file"}.
|
||||
* If the property is a list of more than one name then the names are separated
|
||||
* by a comma character. Each provider class is a {@code public} class with a
|
||||
* {@code public} constructor that has one formal parameter of type {@code
|
||||
* FileSystemProvider}. If the provider class is in a named module then the module
|
||||
* exports the package containing the provider class to at least {@code java.base}.
|
||||
* Each provider class is loaded, using the
|
||||
* {@linkplain ClassLoader#getSystemClassLoader() default system class loader},
|
||||
* and instantiated by invoking the constructor. The providers are loaded and
|
||||
* instantiated in the order they are listed in the property.
|
||||
* If this process fails or a provider's scheme is not equal to {@code "file"}
|
||||
* then an unspecified error is thrown. URI schemes are normally compared
|
||||
* without regard to case but for the default provider, the scheme is
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
|
||||
import com.sun.IoOverNio;
|
||||
import jdk.internal.access.JavaSecurityPropertiesAccess;
|
||||
import jdk.internal.event.EventHelper;
|
||||
import jdk.internal.event.SecurityPropertyModificationEvent;
|
||||
@@ -94,6 +95,16 @@ public final class Security {
|
||||
}
|
||||
|
||||
private static void initialize() {
|
||||
boolean allowIoOverNioBackup = IoOverNio.ALLOW_IO_OVER_NIO.get();
|
||||
try {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(false);
|
||||
initialize0();
|
||||
} finally {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(allowIoOverNioBackup);
|
||||
}
|
||||
}
|
||||
|
||||
private static void initialize0() {
|
||||
props = new Properties();
|
||||
boolean overrideAll = false;
|
||||
|
||||
@@ -123,7 +134,6 @@ public final class Security {
|
||||
props.getProperty(key));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean loadProps(File masterFile, String extraPropFile, boolean overrideAll) {
|
||||
|
||||
@@ -57,6 +57,7 @@ import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.sun.IoOverNio;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.module.ModulePatcher.PatchedModuleReader;
|
||||
@@ -737,11 +738,17 @@ public class BuiltinClassLoader
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
private Class<?> findClassInModuleOrNull(LoadedModule loadedModule, String cn) {
|
||||
if (System.getSecurityManager() == null) {
|
||||
return defineClass(cn, loadedModule);
|
||||
} else {
|
||||
PrivilegedAction<Class<?>> pa = () -> defineClass(cn, loadedModule);
|
||||
return AccessController.doPrivileged(pa);
|
||||
boolean allowIoOverNioBackup = IoOverNio.ALLOW_IO_OVER_NIO.get();
|
||||
try {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(false);
|
||||
if (System.getSecurityManager() == null) {
|
||||
return defineClass(cn, loadedModule);
|
||||
} else {
|
||||
PrivilegedAction<Class<?>> pa = () -> defineClass(cn, loadedModule);
|
||||
return AccessController.doPrivileged(pa);
|
||||
}
|
||||
} finally {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(allowIoOverNioBackup);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,32 +760,38 @@ public class BuiltinClassLoader
|
||||
@SuppressWarnings("removal")
|
||||
private Class<?> findClassOnClassPathOrNull(String cn) {
|
||||
String path = cn.replace('.', '/').concat(".class");
|
||||
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
|
||||
}
|
||||
boolean allowIoOverNioBackup = IoOverNio.ALLOW_IO_OVER_NIO.get();
|
||||
try {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(false);
|
||||
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;
|
||||
}
|
||||
};
|
||||
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);
|
||||
}
|
||||
} finally {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(allowIoOverNioBackup);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package jdk.internal.loader;
|
||||
|
||||
import com.sun.IoOverNio;
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.ref.CleanerFactory;
|
||||
import jdk.internal.util.StaticProperty;
|
||||
@@ -122,13 +123,17 @@ public final class NativeLibraries {
|
||||
if (!isBuiltin) {
|
||||
name = AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
public String run() {
|
||||
boolean allowIoOverNioBackup = IoOverNio.ALLOW_IO_OVER_NIO.get();
|
||||
try {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(false);
|
||||
if (loadLibraryOnlyIfPresent && !file.exists()) {
|
||||
return null;
|
||||
}
|
||||
return file.getCanonicalPath();
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
} finally {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(allowIoOverNioBackup);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -339,8 +344,14 @@ public final class NativeLibraries {
|
||||
// will include the error message from dlopen to provide diagnostic information
|
||||
return AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
public Boolean run() {
|
||||
File file = new File(name);
|
||||
return file.exists();
|
||||
boolean allowIoOverNioBackup = IoOverNio.ALLOW_IO_OVER_NIO.get();
|
||||
try {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(false);
|
||||
File file = new File(name);
|
||||
return file.exists();
|
||||
} finally {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(allowIoOverNioBackup);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1559,4 +1559,8 @@ public class FileChannelImpl
|
||||
assert fileLockTable != null;
|
||||
fileLockTable.remove(fli);
|
||||
}
|
||||
|
||||
public FileDescriptor getFD() {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ import javax.security.auth.x500.X500Principal;
|
||||
import java.net.SocketPermission;
|
||||
import java.net.NetPermission;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.sun.IoOverNio;
|
||||
import jdk.internal.access.JavaSecurityAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.util.StaticProperty;
|
||||
@@ -309,6 +311,16 @@ public class PolicyFile extends java.security.Policy {
|
||||
* initialize the Policy object.
|
||||
*/
|
||||
private void init(URL url) {
|
||||
boolean allowIoOverNioBackup = IoOverNio.ALLOW_IO_OVER_NIO.get();
|
||||
try {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(false);
|
||||
init0(url);
|
||||
} finally {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(allowIoOverNioBackup);
|
||||
}
|
||||
}
|
||||
|
||||
private void init0(URL url) {
|
||||
// Properties are set once for each init(); ignore changes
|
||||
// between diff invocations of initPolicyFile(policy, url, info).
|
||||
String numCacheStr =
|
||||
@@ -1095,6 +1107,17 @@ public class PolicyFile extends java.security.Policy {
|
||||
*/
|
||||
private PermissionCollection getPermissions(Permissions perms,
|
||||
ProtectionDomain pd ) {
|
||||
boolean allowIoOverNioBackup = IoOverNio.ALLOW_IO_OVER_NIO.get();
|
||||
try {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(false);
|
||||
return getPermissions0(perms, pd);
|
||||
} finally {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(allowIoOverNioBackup);
|
||||
}
|
||||
}
|
||||
|
||||
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_getFilePointer(JNIEnv *env, jobject this) {
|
||||
Java_java_io_RandomAccessFile_getFilePointer0(JNIEnv *env, jobject this) {
|
||||
FD fd;
|
||||
jlong ret;
|
||||
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
|
||||
package sun.nio.fs;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.spi.FileTypeDetector;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
|
||||
@@ -34,6 +36,14 @@ public class DefaultFileTypeDetector {
|
||||
|
||||
public static FileTypeDetector create() {
|
||||
FileSystemProvider provider = FileSystems.getDefault().provider();
|
||||
return ((UnixFileSystemProvider)provider).getFileTypeDetector();
|
||||
if (provider instanceof UnixFileSystemProvider unixProvider) {
|
||||
return unixProvider.getFileTypeDetector();
|
||||
}
|
||||
return new FileTypeDetector() {
|
||||
@Override
|
||||
public String probeContentType(Path path) throws IOException {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,8 +199,9 @@ class UnixChannelFactory {
|
||||
if (flags.createNew) {
|
||||
byte[] pathForSysCall = path.asByteArray();
|
||||
|
||||
// throw exception if file name is "." to avoid confusing error
|
||||
if ((pathForSysCall[pathForSysCall.length-1] == '.') &&
|
||||
// throw exception if file name is "." or "" to avoid confusing error
|
||||
if ((pathForSysCall.length == 0) || // TODO Separate pull request.
|
||||
(pathForSysCall[pathForSysCall.length-1] == '.') &&
|
||||
(pathForSysCall.length == 1 ||
|
||||
(pathForSysCall[pathForSysCall.length-2] == '/')))
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.net.*;
|
||||
import java.security.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.sun.IoOverNio;
|
||||
import sun.security.util.Debug;
|
||||
|
||||
/**
|
||||
@@ -126,8 +127,18 @@ public final class NativePRNG extends SecureRandomSpi {
|
||||
/**
|
||||
* Create a RandomIO object for all I/O of this Variant type.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
private static RandomIO initIO(final Variant v) {
|
||||
boolean allowIoOverNioBackup = IoOverNio.ALLOW_IO_OVER_NIO.get();
|
||||
try {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(false);
|
||||
return initIOImpl(v);
|
||||
} finally {
|
||||
IoOverNio.ALLOW_IO_OVER_NIO.set(allowIoOverNioBackup);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private static RandomIO initIOImpl(final Variant v) {
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedAction<>() {
|
||||
@Override
|
||||
|
||||
@@ -53,6 +53,7 @@ import java.security.AccessController;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
@@ -1178,53 +1179,104 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
return contentView.getWindowLayerPtr();
|
||||
}
|
||||
|
||||
private final static int INVOKE_LATER_DISABLED = 0;
|
||||
private final static int INVOKE_LATER_AUTO = 1;
|
||||
private final static int INVOKE_LATER_ENABLED = 2;
|
||||
|
||||
private final static int INVOKE_LATER_FLUSH_BUFFERS = getInvokeLaterMode();
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private final static boolean INVOKE_LATER_FLUSH_BUFFERS
|
||||
= Boolean.parseBoolean(AccessController.doPrivileged(
|
||||
new GetPropertyAction("awt.mac.flushBuffers.invokeLater", "false")));
|
||||
private static int getInvokeLaterMode() {
|
||||
final String invokeLaterKey = "awt.mac.flushBuffers.invokeLater";
|
||||
final String invokeLaterArg = AccessController.doPrivileged(
|
||||
new GetPropertyAction(invokeLaterKey));
|
||||
final int result;
|
||||
if (invokeLaterArg == null) {
|
||||
// default = 'auto':
|
||||
result = INVOKE_LATER_AUTO;
|
||||
} else {
|
||||
switch (invokeLaterArg.toLowerCase()) {
|
||||
default:
|
||||
case "auto":
|
||||
result = INVOKE_LATER_AUTO;
|
||||
break;
|
||||
case "false":
|
||||
result = INVOKE_LATER_DISABLED;
|
||||
break;
|
||||
case "true":
|
||||
result = INVOKE_LATER_ENABLED;
|
||||
break;
|
||||
}
|
||||
logger.info("CPlatformWindow: property \"{0}={1}\", using invokeLater={2}.",
|
||||
invokeLaterKey, invokeLaterArg,
|
||||
(result == INVOKE_LATER_DISABLED) ? "false"
|
||||
: ((result == INVOKE_LATER_AUTO) ? "auto" : "true"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private final static int INVOKE_LATER_COUNT = 5;
|
||||
private final static AtomicInteger invokeLaterCount = new AtomicInteger();
|
||||
/** per window counter of remaining invokeLater calls */
|
||||
private final AtomicInteger invokeLaterCount = new AtomicInteger();
|
||||
|
||||
// Specific class needed to get obvious stack traces:
|
||||
private final class EmptyRunnable implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
// Posting an empty to flush the EventQueue without blocking the main thread
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("CPlatformWindow.flushBuffers: run() invoked on {0}",
|
||||
getIdentifier(target));
|
||||
}
|
||||
}
|
||||
};
|
||||
private final EmptyRunnable emptyTask = new EmptyRunnable();
|
||||
|
||||
void flushBuffers() {
|
||||
// only 1 usage by deliverMoveResizeEvent():
|
||||
if (isVisible() && !nativeBounds.isEmpty() && !isFullScreenMode) {
|
||||
// Runnable needed to get obvious stack traces:
|
||||
final Runnable emptyTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Posting an empty to flush the EventQueue without blocking the main thread
|
||||
logger.fine("CPlatformWindow.flushBuffers: run() invoked on {0}", target);
|
||||
}
|
||||
};
|
||||
|
||||
// use the system property 'awt.mac.flushBuffers.invokeLater' to 'true' (default: false)
|
||||
// use the system property 'awt.mac.flushBuffers.invokeLater' to true/auto (default: auto)
|
||||
// to avoid deadlocks caused by the LWCToolkit.invokeAndWait() call below:
|
||||
boolean useInvokeLater = INVOKE_LATER_FLUSH_BUFFERS;
|
||||
boolean useInvokeLater;
|
||||
|
||||
if (!useInvokeLater && (peer != null)) {
|
||||
final GraphicsDevice device = peer.getGraphicsConfiguration().getDevice();
|
||||
if (device instanceof CGraphicsDevice) {
|
||||
// JBR-5497: avoid deadlock in mirroring mode (laptop + external screen):
|
||||
useInvokeLater = ((CGraphicsDevice)device).isMirroring();
|
||||
logger.fine("CPlatformWindow.flushBuffers: CGraphicsDevice.isMirroring = {0}", useInvokeLater);
|
||||
}
|
||||
}
|
||||
// JBR-5497: keep few more invokeLater() when computer returns from sleep or displayChanged()
|
||||
// to avoid deadlocks until solved definitely:
|
||||
if (useInvokeLater) {
|
||||
// reset to max count:
|
||||
invokeLaterCount.set(INVOKE_LATER_COUNT);
|
||||
} else {
|
||||
final int prev = invokeLaterCount.get();
|
||||
if (prev > 0) {
|
||||
invokeLaterCount.compareAndSet(prev, prev - 1);
|
||||
switch (INVOKE_LATER_FLUSH_BUFFERS) {
|
||||
case INVOKE_LATER_DISABLED:
|
||||
useInvokeLater = false;
|
||||
break;
|
||||
default:
|
||||
case INVOKE_LATER_AUTO:
|
||||
useInvokeLater = false;
|
||||
if (peer != null) {
|
||||
final GraphicsDevice device = peer.getGraphicsConfiguration().getDevice();
|
||||
if (device instanceof CGraphicsDevice) {
|
||||
// JBR-5497: avoid deadlock in mirroring mode (laptop + external screen):
|
||||
useInvokeLater = ((CGraphicsDevice)device).isMirroring();
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("CPlatformWindow.flushBuffers: CGraphicsDevice.isMirroring = {0}",
|
||||
useInvokeLater);
|
||||
}
|
||||
}
|
||||
}
|
||||
// JBR-5497: keep few more invokeLater() when computer returns from sleep or displayChanged()
|
||||
// to avoid deadlocks until solved definitely:
|
||||
if (useInvokeLater) {
|
||||
// reset to max count:
|
||||
invokeLaterCount.set(INVOKE_LATER_COUNT);
|
||||
} else {
|
||||
final int prev = invokeLaterCount.get();
|
||||
if (prev > 0) {
|
||||
invokeLaterCount.compareAndSet(prev, prev - 1);
|
||||
useInvokeLater = true;
|
||||
}
|
||||
}
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("CPlatformWindow.flushBuffers: useInvokeLater = {0} (count = {1})",
|
||||
useInvokeLater, invokeLaterCount.get());
|
||||
}
|
||||
break;
|
||||
case INVOKE_LATER_ENABLED:
|
||||
useInvokeLater = true;
|
||||
}
|
||||
}
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("CPlatformWindow.flushBuffers: useInvokeLater = {0} (count = {1})",
|
||||
useInvokeLater, invokeLaterCount.get());
|
||||
break;
|
||||
}
|
||||
try {
|
||||
// check invokeAndWait: KO (operations require AWTLock and main thread)
|
||||
@@ -1232,11 +1284,19 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
if (useInvokeLater) {
|
||||
LWCToolkit.invokeLater(emptyTask, target);
|
||||
} else {
|
||||
logger.fine("CPlatformWindow.flushBuffers: enter LWCToolkit.invokeAndWait(empty) on target = {0}", target);
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("CPlatformWindow.flushBuffers: enter " +
|
||||
"LWCToolkit.invokeAndWait(emptyTask) on target = {0}",
|
||||
getIdentifier(target));
|
||||
}
|
||||
|
||||
LWCToolkit.invokeAndWait(emptyTask, target);
|
||||
|
||||
logger.fine("CPlatformWindow.flushBuffers: exit LWCToolkit.invokeAndWait(empty) on target = {0}", target);
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("CPlatformWindow.flushBuffers: exit " +
|
||||
"LWCToolkit.invokeAndWait(emptyTask) on target = {0}",
|
||||
getIdentifier(target));
|
||||
}
|
||||
}
|
||||
} catch (InvocationTargetException ite) {
|
||||
logger.severe("CPlatformWindow.flushBuffers: exception occurred: ", ite);
|
||||
@@ -1244,6 +1304,15 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
}
|
||||
}
|
||||
|
||||
private static String getIdentifier(Window t) {
|
||||
if (t == null) {
|
||||
return "null";
|
||||
}
|
||||
return t.getClass().getName()
|
||||
+ "['" + Objects.toString(t.getName(), "")
|
||||
+ "' @" + Integer.toHexString(System.identityHashCode(t)) + ']';
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get a pointer to the native view from the PlatformWindow.
|
||||
*/
|
||||
|
||||
@@ -105,6 +105,7 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
double effectiveScale; // protected by dataLock
|
||||
private final WLSize wlSize = new WLSize();
|
||||
boolean repositionPopup = false; // protected by dataLock
|
||||
boolean resizePending = false; // protected by dataLock
|
||||
|
||||
static {
|
||||
initIDs();
|
||||
@@ -495,6 +496,7 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
return repositionPopup;
|
||||
}
|
||||
}
|
||||
|
||||
private void markPopupNeedsReposition() {
|
||||
synchronized (dataLock) {
|
||||
repositionPopup = true;
|
||||
@@ -507,6 +509,24 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean resizePending() {
|
||||
synchronized (dataLock) {
|
||||
return resizePending;
|
||||
}
|
||||
}
|
||||
|
||||
private void markResizePending() {
|
||||
synchronized (dataLock) {
|
||||
resizePending = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void resizeCompleted() {
|
||||
synchronized (dataLock) {
|
||||
resizePending = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setBounds(int newX, int newY, int newWidth, int newHeight, int op) {
|
||||
Dimension newSize = constrainSize(newWidth, newHeight);
|
||||
boolean positionChanged = (op == SET_BOUNDS || op == SET_LOCATION);
|
||||
@@ -532,7 +552,10 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
|
||||
if (sizeChanged) {
|
||||
setSizeTo(newSize.width, newSize.height);
|
||||
if (!isSizeBeingConfigured()) {
|
||||
wlSize.deriveFromJavaSize(newSize.width, newSize.height);
|
||||
markResizePending();
|
||||
}
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine(String.format("%s is resizing its buffer to %dx%d pixels",
|
||||
this, getBufferWidth(), getBufferHeight()));
|
||||
@@ -558,18 +581,6 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
}
|
||||
|
||||
private void setSizeTo(int newWidth, int newHeight) {
|
||||
if (isSizeBeingConfigured() && wlSize.hasPixelSizeSet()) {
|
||||
// Must be careful not to override the size of the Wayland surface because
|
||||
// some implementations (Weston) react badly when the size of the surface
|
||||
// mismatches the configured size. We can't always precisely derive the surface
|
||||
// size from the Java (client) size because of scaling rounding errors.
|
||||
wlSize.setJavaSize(newWidth, newHeight);
|
||||
} else {
|
||||
wlSize.deriveFromJavaSize(newWidth, newHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public int getBufferWidth() {
|
||||
return wlSize.getPixelWidth();
|
||||
}
|
||||
@@ -1454,6 +1465,16 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
}
|
||||
|
||||
int surfaceUnitsToJavaSize(int value) {
|
||||
if (!WLGraphicsEnvironment.isDebugScaleEnabled()) {
|
||||
return value;
|
||||
} else {
|
||||
synchronized (dataLock) {
|
||||
return (int) Math.ceil(value * displayScale / effectiveScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value in the Java coordinate system into the Wayland
|
||||
* surface-local coordinate system.
|
||||
@@ -1494,7 +1515,8 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
|
||||
boolean isWlPopup = targetIsWlPopup();
|
||||
if (isWlPopup) { // Only popups provide (relative) location
|
||||
boolean acceptNewLocation = !popupNeedsReposition();
|
||||
if (isWlPopup && acceptNewLocation) { // Only popups provide (relative) location
|
||||
int newX = surfaceUnitsToJavaUnits(newSurfaceX);
|
||||
int newY = surfaceUnitsToJavaUnits(newSurfaceY);
|
||||
|
||||
@@ -1511,8 +1533,12 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
// From xdg-shell.xml: "If the width or height arguments are zero,
|
||||
// it means the client should decide its own window dimension".
|
||||
boolean clientDecidesDimension = newSurfaceWidth == 0 || newSurfaceHeight == 0;
|
||||
if (!clientDecidesDimension) {
|
||||
changeSizeToConfigured(newSurfaceWidth, newSurfaceHeight, maximized);
|
||||
boolean desiredSize =
|
||||
(wlSize.javaSize.width == surfaceUnitsToJavaSize(newSurfaceWidth)
|
||||
&& wlSize.javaSize.height == surfaceUnitsToJavaSize(newSurfaceHeight));
|
||||
boolean acceptNewSize = !resizePending() || maximized || desiredSize;
|
||||
if (!clientDecidesDimension && acceptNewSize) {
|
||||
changeSizeToConfigured(newSurfaceWidth, newSurfaceHeight);
|
||||
}
|
||||
|
||||
if (!surfaceAssigned) {
|
||||
@@ -1534,16 +1560,13 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
}
|
||||
|
||||
private void changeSizeToConfigured(int newSurfaceWidth, int newSurfaceHeight, boolean honorSurfaceSize) {
|
||||
private void changeSizeToConfigured(int newSurfaceWidth, int newSurfaceHeight) {
|
||||
resizeCompleted();
|
||||
wlSize.deriveFromSurfaceSize(newSurfaceWidth, newSurfaceHeight);
|
||||
int newWidth = wlSize.getJavaWidth();
|
||||
int newHeight = wlSize.getJavaHeight();
|
||||
try {
|
||||
// When 'honorSurfaceSize' is in effect, we shall not confuse the size given by the server with
|
||||
// the size set by the user. The former originates from the surface size in surface-local coordinates,
|
||||
// while the latter is set in the client (Java) units. These are not always precisely convertible
|
||||
// when the scale differs from 100%.
|
||||
setSizeIsBeingConfigured(honorSurfaceSize);
|
||||
setSizeIsBeingConfigured(true);
|
||||
performUnlocked(() -> target.setSize(newWidth, newHeight));
|
||||
} finally {
|
||||
setSizeIsBeingConfigured(false);
|
||||
@@ -1748,8 +1771,8 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
|
||||
void deriveFromSurfaceSize(int width, int height) {
|
||||
synchronized (dataLock) {
|
||||
javaSize.width = surfaceUnitsToJavaUnits(width);
|
||||
javaSize.height = surfaceUnitsToJavaUnits(height);
|
||||
javaSize.width = surfaceUnitsToJavaSize(width);
|
||||
javaSize.height = surfaceUnitsToJavaSize(height);
|
||||
pixelSize.width = width * displayScale;
|
||||
pixelSize.height = height * displayScale;
|
||||
surfaceSize.width = width;
|
||||
|
||||
@@ -240,7 +240,7 @@ vmTestbase/nsk/jdb/options/listconnectors/listconnectors001/listconnectors001.ja
|
||||
vmTestbase/nsk/jdi/LaunchingConnector/launch/launch001/TestDescription.java initial_run windows-all
|
||||
vmTestbase/nsk/jdi/LaunchingConnector/launch/launch003/TestDescription.java initial_run windows-all
|
||||
vmTestbase/nsk/jdi/LaunchingConnector/launchnosuspend/launchnosuspend001/TestDescription.java initial_run windows-all
|
||||
vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001/TestDescription.java JBR-7585 macosx-all
|
||||
vmTestbase/nsk/jdi/MethodExitRequest/addClassFilter_rt/filter_rt001/TestDescription.java JBR-7585 macosx-all,linux-all
|
||||
vmTestbase/nsk/jdi/ThreadReference/stop/stop001/TestDescription.java 7034630 generic-all
|
||||
vmTestbase/nsk/jdi/ReferenceType/instances/instances002/instances002.java initial_run linux-all
|
||||
vmTestbase/nsk/jdi/Value/type/type002/type002.java JBR-7553 macosx-x64
|
||||
|
||||
164
test/jdk/java/io/IoOverNio/FileInputStreamTest.java
Normal file
164
test/jdk/java/io/IoOverNio/FileInputStreamTest.java
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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.*;
|
||||
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.*;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
98
test/jdk/java/io/IoOverNio/FileOutputStreamTest.java
Normal file
98
test/jdk/java/io/IoOverNio/FileOutputStreamTest.java
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.*;
|
||||
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.*;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
368
test/jdk/java/io/IoOverNio/FileTest.java
Normal file
368
test/jdk/java/io/IoOverNio/FileTest.java
Normal file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* 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.*;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import testNio.ManglingFileSystemProvider;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
|
||||
import static java.util.Arrays.sort;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class FileTest {
|
||||
@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() 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 {
|
||||
Files.delete(path);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@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 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 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.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 {
|
||||
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();
|
||||
|
||||
File dir = temporaryFolder.newFolder();
|
||||
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; echo")
|
||||
.start()
|
||||
.waitFor());
|
||||
|
||||
try {
|
||||
assertTrue(unixSocket.exists());
|
||||
} finally {
|
||||
ncProcess.destroy();
|
||||
}
|
||||
} finally {
|
||||
new ProcessBuilder("rm", "-rf", shortTmpDir).start();
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
// }
|
||||
}
|
||||
205
test/jdk/java/io/IoOverNio/RandomAccessFileTest.java
Normal file
205
test/jdk/java/io/IoOverNio/RandomAccessFileTest.java
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 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.*;
|
||||
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.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
||||
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 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);
|
||||
|
||||
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")) {
|
||||
rac.setLength(content.length() + 2);
|
||||
rac.seek(0);
|
||||
assertEquals(rac.readLine(), "h3110" + extraContent.substring(0, 2));
|
||||
}
|
||||
|
||||
// TODO Bigger length.
|
||||
}
|
||||
|
||||
@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()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
205
test/jdk/java/io/IoOverNio/testNio/ManglingFileChannel.java
Normal file
205
test/jdk/java/io/IoOverNio/testNio/ManglingFileChannel.java
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
111
test/jdk/java/io/IoOverNio/testNio/ManglingFileSystem.java
Normal file
111
test/jdk/java/io/IoOverNio/testNio/ManglingFileSystem.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.*;
|
||||
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("\\\\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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* 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.*;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
public class ManglingFileSystemProvider extends FileSystemProvider {
|
||||
final FileSystemProvider defaultProvider;
|
||||
final FileSystem defaultFs;
|
||||
final ManglingFileSystem manglingFs = new ManglingFileSystem(this);
|
||||
;
|
||||
|
||||
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;
|
||||
|
||||
public static final String extraContent = "3x7r4";
|
||||
|
||||
public static void resetTricks() {
|
||||
mangleFileContent = false;
|
||||
readExtraFileContent = false;
|
||||
manglePaths = false;
|
||||
mangleOnlyFileName = false;
|
||||
denyAccessToEverything = false;
|
||||
allFilesAreEmptyDirectories = false;
|
||||
prohibitFileTreeModifications = false;
|
||||
addEliteToEveryDirectoryListing = false;
|
||||
}
|
||||
|
||||
static {
|
||||
// TODO It's a tricky workaround. Would be better to get rid of it.
|
||||
Class<?> ignored = ManglingPath.class;
|
||||
ignored = ManglingBasicFileAttributeView.class;
|
||||
ignored = ManglingBasicFileAttributes.class;
|
||||
ignored = ManglingDirectoryStream.ManglingPathIterator.class;
|
||||
ignored = ManglingDirectoryStream.class;
|
||||
ignored = ManglingDosFileAttributeView.class;
|
||||
ignored = ManglingFileChannel.class;
|
||||
ignored = ManglingPosixFileAttributeView.class;
|
||||
ignored = ManglingPosixFileAttributes.class;
|
||||
}
|
||||
|
||||
private final static byte[] manglingTable = new byte[256];
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public ManglingFileSystemProvider(FileSystemProvider defaultProvider) {
|
||||
super();
|
||||
this.defaultProvider = defaultProvider;
|
||||
this.defaultFs = defaultProvider.getFileSystem(URI.create("file:/"));
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
static Path unwrap(Path path) {
|
||||
if (path instanceof ManglingPath pcp) {
|
||||
return pcp.delegate;
|
||||
}
|
||||
throw new IllegalArgumentException("Wrong path " + path + " (class: " + path.getClass() + ")");
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
179
test/jdk/java/io/IoOverNio/testNio/ManglingPath.java
Normal file
179
test/jdk/java/io/IoOverNio/testNio/ManglingPath.java
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* 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.*;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ManglingPath implements Path {
|
||||
private final ManglingFileSystem fileSystem;
|
||||
final Path delegate;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.*;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -36,8 +36,8 @@
|
||||
* @requires !vm.musl
|
||||
* @requires vm.flagless
|
||||
* @library /test/lib
|
||||
* @run main/othervm/native/timeout=300 -Djava.security.manager=allow Basic
|
||||
* @run main/othervm/native/timeout=300 -Djava.security.manager=allow -Djdk.lang.Process.launchMechanism=fork Basic
|
||||
* @run main/othervm/native/timeout=300 -Djbr.java.io.use.nio=false -Djava.security.manager=allow Basic
|
||||
* @run main/othervm/native/timeout=300 -Djbr.java.io.use.nio=false -Djava.security.manager=allow -Djdk.lang.Process.launchMechanism=fork Basic
|
||||
* @author Martin Buchholz
|
||||
*/
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
* java.base/jdk.internal.misc
|
||||
* @requires (os.family == "linux" & !vm.musl)
|
||||
* @library /test/lib
|
||||
* @run main/othervm/timeout=300 -Djava.security.manager=allow -Djdk.lang.Process.launchMechanism=posix_spawn Basic
|
||||
* @run main/othervm/timeout=300 -Djbr.java.io.use.nio=false -Djava.security.manager=allow -Djdk.lang.Process.launchMechanism=posix_spawn Basic
|
||||
*/
|
||||
|
||||
import java.lang.ProcessBuilder.Redirect;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
* @bug 4244896
|
||||
* @summary Test for the various platform specific implementations of
|
||||
* destroyForcibly.
|
||||
* @run main/othervm -Djbr.java.io.use.nio=false DestroyTest
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
||||
40
test/jdk/java/nio/file/spi/CustomSystemClassLoader.java
Normal file
40
test/jdk/java/nio/file/spi/CustomSystemClassLoader.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
|
||||
/**
|
||||
* Use by tests in SetDefaultProvider to test startup with a custom default file system
|
||||
* provider and a custom system class loader.
|
||||
*/
|
||||
|
||||
public class CustomSystemClassLoader extends ClassLoader {
|
||||
public CustomSystemClassLoader(ClassLoader parent) {
|
||||
super(parent);
|
||||
|
||||
// use default file system
|
||||
FileSystem fs = FileSystems.getDefault();
|
||||
var path = fs.getPath("foo");
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
* @bug 4313887 7006126 8142968 8178380 8183320 8210112 8266345 8263940
|
||||
* @modules jdk.jartool
|
||||
* @library /test/lib
|
||||
* @build SetDefaultProvider TestProvider m/* jdk.test.lib.process.ProcessTools
|
||||
* @build SetDefaultProvider TestProvider m/* jdk.test.lib.process.ProcessTools CustomSystemClassLoader
|
||||
* @run testng/othervm SetDefaultProvider
|
||||
* @summary Runs tests with -Djava.nio.file.spi.DefaultFileSystemProvider set on
|
||||
* the command line to override the default file system provider
|
||||
@@ -37,6 +37,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.spi.ToolProvider;
|
||||
@@ -180,6 +181,56 @@ public class SetDefaultProvider {
|
||||
assertEquals(exitValue, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test file system provider on class path in conjunction with a custom system
|
||||
* class loader that uses the file system API during its initialization.
|
||||
*/
|
||||
public void testCustomSystemClassLoader() throws Exception {
|
||||
String testClasses = System.getProperty("test.classes");
|
||||
int exitValue = exec(SET_DEFAULT_FSP,
|
||||
"-Djava.system.class.loader=CustomSystemClassLoader",
|
||||
"-cp", ofClasspath(testClasses, classes("m")),
|
||||
"p.Main");
|
||||
assertEquals(exitValue, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a class path from the given paths.
|
||||
*/
|
||||
private String ofClasspath(String... paths) {
|
||||
return String.join(File.pathSeparator, paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the file system provider located in a jar with
|
||||
* -Djava.util.zip.use.nio.for.zip.file.access=true
|
||||
* that makes ZipFile use NIO to read the jar.
|
||||
*/
|
||||
public void testClassPathWithFileSystemProviderJarAndNioForZipFile() throws Exception {
|
||||
String testClasses = System.getProperty("test.classes");
|
||||
Path fspJar = Path.of("testFileSystemProvider.jar");
|
||||
Files.deleteIfExists(fspJar);
|
||||
createFileSystemProviderJar(fspJar, Path.of(testClasses));
|
||||
String jarFile = createModularJar();
|
||||
String classpath = ofClasspath(fspJar.toString(), jarFile, testClasses);
|
||||
int exitValue = exec(SET_DEFAULT_FSP, "-Djava.util.zip.use.nio.for.zip.file.access=true",
|
||||
"-cp", classpath, "p.Main");
|
||||
assertEquals(exitValue, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the directory containing the classes for the given module.
|
||||
*/
|
||||
private static String classes(String mn) {
|
||||
String mp = System.getProperty("jdk.module.path");
|
||||
return Arrays.stream(mp.split(File.pathSeparator))
|
||||
.map(e -> Path.of(e, mn))
|
||||
.filter(Files::isDirectory)
|
||||
.findAny()
|
||||
.map(Path::toString)
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the directory containing the classes for module "m".
|
||||
*/
|
||||
|
||||
40
test/jdk/jb/java/nio/file/spi/ProbeContentType.java
Normal file
40
test/jdk/jb/java/nio/file/spi/ProbeContentType.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 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 Verifies that Files.probeContentType() does not throw
|
||||
* when used with a custom FS provider
|
||||
* @library /test/lib
|
||||
* @build TestProvider
|
||||
* @run main/othervm -Djava.nio.file.spi.DefaultFileSystemProvider=TestProvider ProbeContentType
|
||||
*/
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class ProbeContentType {
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println(Files.probeContentType(Path.of(".")));
|
||||
}
|
||||
}
|
||||
@@ -74,47 +74,59 @@ public class WLPopupLocation {
|
||||
SwingUtilities.invokeAndWait(WLPopupLocation::initPopup);
|
||||
pause(robot);
|
||||
|
||||
int w1 = 150, h1 = 200;
|
||||
int x1 = 100, y1 = 100;
|
||||
System.out.printf("Action: locate to (%d, %d), set size (%d, %d)\n", x1, y1, w1, h1);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setVisible(true);
|
||||
popup.setSize(w1, h1);
|
||||
popup.setLocation(x1, y1);
|
||||
});
|
||||
if (popup.getSize().width != w1 || popup.getSize().height != h1) {
|
||||
throw new RuntimeException(String.format("Incorrect size (%d, %d), expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
|
||||
}
|
||||
if (popup.getBounds().x != x1 || popup.getBounds().y != y1) {
|
||||
throw new RuntimeException(String.format("Wrong location (via getBounds()): (%d, %d). Expected: (%d, %d)", popup.getBounds().x, popup.getBounds().y, x1, y1));
|
||||
}
|
||||
pause(robot);
|
||||
if (popup.getSize().width != h1 || popup.getSize().height != h1) {
|
||||
throw new RuntimeException(String.format("Incorrect size (%d, %d) after robot's wait for idle, expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
|
||||
}
|
||||
if (popup.getBounds().x != x1 || popup.getBounds().y != y1) {
|
||||
throw new RuntimeException(String.format("Wrong location (via getBounds()) after robot's wait for idle: (%d, %d). Expected: (%d, %d)", popup.getBounds().x, popup.getBounds().y, x1, y1));
|
||||
}
|
||||
try {
|
||||
int w1 = 150, h1 = 200;
|
||||
int x1 = 100, y1 = 100;
|
||||
System.out.printf("Action: locate to (%d, %d), set size (%d, %d)\n", x1, y1, w1, h1);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setVisible(true);
|
||||
popup.setSize(2, 5);
|
||||
popup.setSize(89, 17);
|
||||
popup.setSize(11, 3);
|
||||
popup.setSize(w1, h1);
|
||||
popup.setLocation(x1, y1);
|
||||
});
|
||||
int toleranceLevel = getTolerance();
|
||||
|
||||
int x2 = 200, y2 = 200;
|
||||
System.out.printf("Action: set popup size to (%d, %d)\n", x2, y2);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setLocation(x2, y2);
|
||||
});
|
||||
if (popup.getSize().width != w1 || popup.getSize().height != h1) {
|
||||
throw new RuntimeException(String.format("Incorrect size (%d, %d), expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
|
||||
System.out.printf("Real bounds: %s\n", popup.getBounds());
|
||||
if (isOutsideTolerance(w1, h1, popup.getSize().width, popup.getSize().height, toleranceLevel)) {
|
||||
throw new RuntimeException(String.format("Incorrect size (%d, %d), expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
|
||||
}
|
||||
if (isOutsideTolerance(x1, y1, popup.getBounds().x, popup.getBounds().y, toleranceLevel)) {
|
||||
throw new RuntimeException(String.format("Wrong location (via getBounds()): (%d, %d). Expected: (%d, %d)", popup.getBounds().x, popup.getBounds().y, x1, y1));
|
||||
}
|
||||
pause(robot);
|
||||
System.out.printf("Real bounds after a pause: %s\n", popup.getBounds());
|
||||
if (isOutsideTolerance(w1, h1, popup.getSize().width, popup.getSize().height, toleranceLevel)) {
|
||||
throw new RuntimeException(String.format("Incorrect size (%d, %d) after robot's wait for idle, expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
|
||||
}
|
||||
if (isOutsideTolerance(x1, y1, popup.getBounds().x, popup.getBounds().y, toleranceLevel)) {
|
||||
throw new RuntimeException(String.format("Wrong location (via getBounds()) after robot's wait for idle: (%d, %d). Expected: (%d, %d)", popup.getBounds().x, popup.getBounds().y, x1, y1));
|
||||
}
|
||||
|
||||
int x2 = 200, y2 = 200;
|
||||
System.out.printf("Action: set popup location to (%d, %d)\n", x2, y2);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setLocation(x2, y2);
|
||||
});
|
||||
System.out.printf("Real bounds: %s\n", popup.getBounds());
|
||||
if (isOutsideTolerance(w1, h1, popup.getSize().width, popup.getSize().height, toleranceLevel)) {
|
||||
throw new RuntimeException(String.format("Incorrect size (%d, %d), expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
|
||||
}
|
||||
if (isOutsideTolerance(x2, y2, popup.getBounds().x, popup.getBounds().y, toleranceLevel)) {
|
||||
throw new RuntimeException(String.format("Wrong location (via getBounds()): (%d, %d). Expected: (%x, %d)", popup.getBounds().x, popup.getBounds().y, x2, y2));
|
||||
}
|
||||
pause(robot);
|
||||
System.out.printf("Real bounds after a pause: %s\n", popup.getBounds());
|
||||
if (isOutsideTolerance(w1, h1, popup.getSize().width, popup.getSize().height, toleranceLevel)) {
|
||||
throw new RuntimeException(String.format("Incorrect size (%d, %d) after robot's wait for idle, expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
|
||||
}
|
||||
if (isOutsideTolerance(x2, y2, popup.getBounds().x, popup.getBounds().y, toleranceLevel)) {
|
||||
throw new RuntimeException(String.format("Wrong location (via getBounds()) after robot's wait for idle: (%d, %d). Expected: (%d, %d)", popup.getBounds().x, popup.getBounds().y, x2, y2));
|
||||
}
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
if (popup.getBounds().x != x2 || popup.getBounds().y != y2) {
|
||||
throw new RuntimeException(String.format("Wrong location (via getBounds()): (%d, %d). Expected: (%x, %d)", popup.getBounds().x, popup.getBounds().y, x2, y2));
|
||||
}
|
||||
pause(robot);
|
||||
if (popup.getSize().width != w1 || popup.getSize().height != h1) {
|
||||
throw new RuntimeException(String.format("Incorrect size (%d, %d) after robot's wait for idle, expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
|
||||
}
|
||||
if (popup.getBounds().x != x2 || popup.getBounds().y != y2) {
|
||||
throw new RuntimeException(String.format("Wrong location (via getBounds()) after robot's wait for idle: (%d, %d). Expected: (%d, %d)", popup.getBounds().x, popup.getBounds().y, x2, y2));
|
||||
}
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
|
||||
private static void pause(Robot robot) {
|
||||
@@ -122,4 +134,14 @@ public class WLPopupLocation {
|
||||
robot.delay(500);
|
||||
}
|
||||
|
||||
private static int getTolerance() {
|
||||
String uiScaleString = System.getProperty("sun.java2d.uiScale");
|
||||
int tolerance = uiScaleString == null ? 0 : (int) Math.ceil(Double.parseDouble(uiScaleString));
|
||||
System.out.printf("Scale settings: debug scale: %s, tolerance level: %d\n", uiScaleString, tolerance);
|
||||
return tolerance;
|
||||
}
|
||||
|
||||
private static boolean isOutsideTolerance(int expectedX, int expectedY, int realX, int realY, int tolerance) {
|
||||
return Math.abs(realX - expectedX) > tolerance || Math.abs(realY - expectedY) > tolerance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,13 +68,14 @@ public class WLPopupMinSize {
|
||||
throw new RuntimeException("Popup minimum size is not 1000x100 but " + popupMinSize);
|
||||
}
|
||||
|
||||
int tolerance = getTolerance();
|
||||
Dimension popupSize = popup.getSize();
|
||||
System.out.println("Popup size: " + popupSize);
|
||||
if (popupSize.width != 1000 || popupSize.height != 1000) {
|
||||
if (isOutsideTolerance(1000, 1000, popupSize.width, popupSize.height, tolerance)) {
|
||||
throw new RuntimeException("Popup actual size is not 1000x100 but " + popupSize);
|
||||
}
|
||||
} finally {
|
||||
frame.dispose();
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,4 +96,15 @@ public class WLPopupMinSize {
|
||||
// Setting the minimum size at this point must resize the popup window
|
||||
popup.setMinimumSize(new Dimension(1000, 1000));
|
||||
}
|
||||
|
||||
private static int getTolerance() {
|
||||
String uiScaleString = System.getProperty("sun.java2d.uiScale");
|
||||
int tolerance = uiScaleString == null ? 0 : (int) Math.ceil(Double.parseDouble(uiScaleString));
|
||||
System.out.printf("Scale settings: debug scale: %s, tolerance level: %d\n", uiScaleString, tolerance);
|
||||
return tolerance;
|
||||
}
|
||||
|
||||
private static boolean isOutsideTolerance(int expectedX, int expectedY, int realX, int realY, int tolerance) {
|
||||
return Math.abs(realX - expectedX) > tolerance || Math.abs(realY - expectedY) > tolerance;
|
||||
}
|
||||
}
|
||||
@@ -76,65 +76,65 @@ public class WLPopupMoves {
|
||||
pause(robot);
|
||||
|
||||
double uiScale = getUiScale();
|
||||
System.out.printf("UI scale: %.2f.\n", uiScale);
|
||||
int pixelThreshold = uiScale == 1.0 ? 0 : (int) Math.ceil(uiScale);
|
||||
System.out.printf("Pixel threshold for verifications: %d\n", pixelThreshold);
|
||||
int tolerance = getTolerance();
|
||||
|
||||
int w = 120, h = 200;
|
||||
System.out.println("Set popup to (50, 50)");
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(50, 50, w, h);
|
||||
popup.setVisible(true);
|
||||
});
|
||||
verifyBounds("Popup position after setting to (50, 50)\n", 50, 50, w, h, pixelThreshold);
|
||||
pause(robot);
|
||||
verifyBounds("Popup position (50, 50) after robot's pause\n", 50, 50, w, h, pixelThreshold);
|
||||
try {
|
||||
int w = 120, h = 200;
|
||||
System.out.println("Set popup to (50, 50)");
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(50, 50, w, h);
|
||||
popup.setVisible(true);
|
||||
});
|
||||
verifyBounds("Popup position after setting to (50, 50)\n", 50, 50, w, h, tolerance);
|
||||
pause(robot);
|
||||
verifyBounds("Popup position (50, 50) after robot's pause\n", 50, 50, w, h, tolerance);
|
||||
|
||||
System.out.println("Set popup to (100, 100)");
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(100, 100, w, h);
|
||||
});
|
||||
verifyBounds("Popup position after setting to (100, 100)\n", 100, 100, w, h, pixelThreshold);
|
||||
pause(robot);
|
||||
verifyBounds("Popup position (100, 100) after robot's pause\n", 100, 100, w, h, pixelThreshold);
|
||||
System.out.println("Set popup to (100, 100)");
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(100, 100, w, h);
|
||||
});
|
||||
verifyBounds("Popup position after setting to (100, 100)\n", 100, 100, w, h, tolerance);
|
||||
pause(robot);
|
||||
verifyBounds("Popup position (100, 100) after robot's pause\n", 100, 100, w, h, tolerance);
|
||||
|
||||
int x1 = (int) (toolkit.getScreenSize().width / (2 * uiScale));
|
||||
int y1 = (int) (toolkit.getScreenSize().height / (2 * uiScale));
|
||||
System.out.printf("Set popup to (%d, %d)\n", x1, y1);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(x1, y1, w, h);
|
||||
});
|
||||
verifyBounds(String.format("Popup position after setting to (%d, %d)\n", x1, y1), x1, y1, w, h, pixelThreshold);
|
||||
pause(robot);
|
||||
verifyBounds(String.format("Popup position (%d, %d) after robot's pause\n", x1, y1), x1, y1, w, h, pixelThreshold);
|
||||
|
||||
int x2 = (int) (toolkit.getScreenSize().width / uiScale - 10 - w);
|
||||
int y2 = (int) (toolkit.getScreenSize().height / uiScale - 10 - h);
|
||||
System.out.printf("Set popup to (%d, %d). (to the bottom right corner) \n", x2, y2);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(x2, y2, w, h);
|
||||
});
|
||||
verifyBounds(String.format("Popup position after setting to (%d, %d)\n", x2, y2), x2, y2, w, h, pixelThreshold);
|
||||
pause(robot);
|
||||
verifyBounds(String.format("Popup position (%d, %d) after robot's pause\n", x2, y2), x2, y2, w, h, pixelThreshold);
|
||||
int x1 = (int) (toolkit.getScreenSize().width / (2 * uiScale));
|
||||
int y1 = (int) (toolkit.getScreenSize().height / (2 * uiScale));
|
||||
System.out.printf("Set popup to (%d, %d)\n", x1, y1);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(x1, y1, w, h);
|
||||
});
|
||||
verifyBounds(String.format("Popup position after setting to (%d, %d)\n", x1, y1), x1, y1, w, h, tolerance);
|
||||
pause(robot);
|
||||
verifyBounds(String.format("Popup position (%d, %d) after robot's pause\n", x1, y1), x1, y1, w, h, tolerance);
|
||||
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
GraphicsDevice device = ge.getDefaultScreenDevice();
|
||||
GraphicsConfiguration gc = device.getDefaultConfiguration();
|
||||
Insets insets = toolkit.getScreenInsets(gc);
|
||||
int x3 = (int) (toolkit.getScreenSize().width / uiScale - 10 - insets.right);
|
||||
int y3 = (int) (toolkit.getScreenSize().height / uiScale - 10 - insets.bottom);
|
||||
System.out.printf("Set popup to (%d, %d). (to the bottom right corner) \n", x3, y3);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(x2, y2, w, h);
|
||||
});
|
||||
int x3Relocated = x3 - w;
|
||||
int y3Relocated = y3 - h;
|
||||
verifyBounds(String.format("Popup position after setting to (%d, %d)\n", x3, y3), x3Relocated, y3Relocated, w, h, pixelThreshold);
|
||||
pause(robot);
|
||||
verifyBounds(String.format("Popup position (%d, %d) after robot's pause\n", x3, y3), x3Relocated, y3Relocated, w, h, pixelThreshold);
|
||||
int x2 = (int) (toolkit.getScreenSize().width / uiScale - 10 - w);
|
||||
int y2 = (int) (toolkit.getScreenSize().height / uiScale - 10 - h);
|
||||
System.out.printf("Set popup to (%d, %d). (to the bottom right corner) \n", x2, y2);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(x2, y2, w, h);
|
||||
});
|
||||
verifyBounds(String.format("Popup position after setting to (%d, %d)\n", x2, y2), x2, y2, w, h, tolerance);
|
||||
pause(robot);
|
||||
verifyBounds(String.format("Popup position (%d, %d) after robot's pause\n", x2, y2), x2, y2, w, h, tolerance);
|
||||
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
GraphicsDevice device = ge.getDefaultScreenDevice();
|
||||
GraphicsConfiguration gc = device.getDefaultConfiguration();
|
||||
Insets insets = toolkit.getScreenInsets(gc);
|
||||
int x3 = (int) (toolkit.getScreenSize().width / uiScale - 10 - insets.right);
|
||||
int y3 = (int) (toolkit.getScreenSize().height / uiScale - 10 - insets.bottom);
|
||||
System.out.printf("Set popup to (%d, %d). (to the bottom right corner) \n", x3, y3);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(x2, y2, w, h);
|
||||
});
|
||||
int x3Relocated = x3 - w;
|
||||
int y3Relocated = y3 - h;
|
||||
verifyBounds(String.format("Popup position after setting to (%d, %d)\n", x3, y3), x3Relocated, y3Relocated, w, h, tolerance);
|
||||
pause(robot);
|
||||
verifyBounds(String.format("Popup position (%d, %d) after robot's pause\n", x3, y3), x3Relocated, y3Relocated, w, h, tolerance);
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
}
|
||||
|
||||
private static Double getUiScale() {
|
||||
@@ -168,4 +168,15 @@ public class WLPopupMoves {
|
||||
robot.waitForIdle();
|
||||
robot.delay(500);
|
||||
}
|
||||
|
||||
private static int getTolerance() {
|
||||
String uiScaleString = System.getProperty("sun.java2d.uiScale");
|
||||
int tolerance = uiScaleString == null ? 0 : (int) Math.ceil(Double.parseDouble(uiScaleString));
|
||||
System.out.printf("Scale settings: debug scale: %s, tolerance level: %d\n", uiScaleString, tolerance);
|
||||
return tolerance;
|
||||
}
|
||||
|
||||
private static boolean isOutsideTolerance(int expectedX, int expectedY, int realX, int realY, int tolerance) {
|
||||
return Math.abs(realX - expectedX) > tolerance || Math.abs(realY - expectedY) > tolerance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,15 +73,18 @@ public class WLPopupNoSize {
|
||||
SwingUtilities.invokeAndWait(WLPopupNoSize::initPopup);
|
||||
pause(robot);
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> popup.setVisible(true));
|
||||
boolean isVisible1 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isVisible2 = popup.isVisible();
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(() -> popup.setVisible(true));
|
||||
boolean isVisible1 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isVisible2 = popup.isVisible();
|
||||
|
||||
if (!isVisible1 || !isVisible2) {
|
||||
throw new RuntimeException("Expected result: popup is visible");
|
||||
if (!isVisible1 || !isVisible2) {
|
||||
throw new RuntimeException("Expected result: popup is visible");
|
||||
}
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
|
||||
private static void pause(Robot robot) {
|
||||
|
||||
@@ -105,51 +105,45 @@ public class WLPopupResize {
|
||||
SwingUtilities.invokeAndWait(WLPopupResize::showPopup);
|
||||
pause(robot);
|
||||
|
||||
double uiScale = getUiScale();
|
||||
System.out.printf("UI scale: %.2f.\n", uiScale);
|
||||
int pixelThreshold = uiScale == 1.0 ? 0 : (int) Math.ceil(uiScale);
|
||||
System.out.printf("Pixel threshold for verifications: %d\n", pixelThreshold);
|
||||
try {
|
||||
int tolerance = getTolerance();
|
||||
|
||||
int x = 10, y = 20, w = 120, h = 80;
|
||||
System.out.println("Set popup size to (120, 80)");
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(x, y, w, h);
|
||||
});
|
||||
Rectangle bounds = popup.getBounds();
|
||||
boolean isCorrectPosition = x - pixelThreshold <= bounds.x && bounds.x <= x + pixelThreshold &&
|
||||
y - pixelThreshold <= bounds.y && bounds.y <= y + pixelThreshold;
|
||||
if (!isCorrectPosition) {
|
||||
throw new RuntimeException("Popup position has unexpectedly changed. Bounds: " + popup.getBounds());
|
||||
}
|
||||
if (popup.getBounds().width != w || popup.getBounds().height != h) {
|
||||
throw new RuntimeException("Popup size wasn't correctly changed. Bounds: " + popup.getBounds());
|
||||
}
|
||||
pause(robot);
|
||||
System.out.println("Next checks after robot's waiting for idle.");
|
||||
int x = 10, y = 20, w = 120, h = 80;
|
||||
System.out.println("Set popup size to (120, 80)");
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(x, y, w, h);
|
||||
});
|
||||
Rectangle bounds = popup.getBounds();
|
||||
if (isOutsideTolerance(x, y, bounds.x, bounds.y, tolerance)) {
|
||||
throw new RuntimeException("Popup position has unexpectedly changed. Bounds: " + popup.getBounds());
|
||||
}
|
||||
if (isOutsideTolerance(w, h, bounds.width, bounds.height, tolerance)) {
|
||||
throw new RuntimeException("Popup size wasn't correctly changed. Bounds: " + popup.getBounds());
|
||||
}
|
||||
pause(robot);
|
||||
System.out.println("Next checks after robot's waiting for idle.");
|
||||
|
||||
isCorrectPosition = x - pixelThreshold <= bounds.x && bounds.x <= x + pixelThreshold &&
|
||||
y - pixelThreshold <= bounds.y && bounds.y <= y + pixelThreshold;
|
||||
if (!isCorrectPosition) {
|
||||
throw new RuntimeException("Popup position has unexpectedly changed. Bounds: " + popup.getBounds());
|
||||
bounds = popup.getBounds();
|
||||
if (isOutsideTolerance(x, y, bounds.x, bounds.y, tolerance)) {
|
||||
throw new RuntimeException("Popup position has unexpectedly changed. Bounds: " + popup.getBounds());
|
||||
}
|
||||
if (isOutsideTolerance(w, h, bounds.width, bounds.height, tolerance)) {
|
||||
throw new RuntimeException("Popup size wasn't correctly changed. Bounds: " + popup.getBounds());
|
||||
}
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
if (popup.getBounds().width != w || popup.getBounds().height != h) {
|
||||
throw new RuntimeException("Popup size wasn't correctly changed. Bounds: " + popup.getBounds());
|
||||
}
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
|
||||
private static Double getUiScale() {
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
GraphicsDevice device = ge.getDefaultScreenDevice();
|
||||
GraphicsConfiguration gc = device.getDefaultConfiguration();
|
||||
AffineTransform transform = gc.getDefaultTransform();
|
||||
double scaleX = transform.getScaleX();
|
||||
double scaleY = transform.getScaleY();
|
||||
if (scaleX != scaleY) {
|
||||
System.out.println("Skip test due to non-uniform display scale");
|
||||
System.exit(0);
|
||||
}
|
||||
return scaleX;
|
||||
private static int getTolerance() {
|
||||
String uiScaleString = System.getProperty("sun.java2d.uiScale");
|
||||
int tolerance = uiScaleString == null ? 0 : (int) Math.ceil(Double.parseDouble(uiScaleString));
|
||||
System.out.printf("Scale settings: debug scale: %s, tolerance level: %d\n", uiScaleString, tolerance);
|
||||
return tolerance;
|
||||
}
|
||||
|
||||
private static boolean isOutsideTolerance(int expectedX, int expectedY, int realX, int realY, int tolerance) {
|
||||
return Math.abs(realX - expectedX) > tolerance || Math.abs(realY - expectedY) > tolerance;
|
||||
}
|
||||
|
||||
private static void pause(Robot robot) {
|
||||
|
||||
@@ -73,57 +73,59 @@ public class WLPopupVisibility {
|
||||
SwingUtilities.invokeAndWait(WLPopupVisibility::initPopup);
|
||||
pause(robot);
|
||||
|
||||
System.out.println("Action: set the popup visible");
|
||||
SwingUtilities.invokeAndWait(() -> popup.setVisible(true));
|
||||
boolean isVisible1 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isVisible2 = popup.isVisible();
|
||||
try {
|
||||
System.out.println("Action: set the popup visible");
|
||||
SwingUtilities.invokeAndWait(() -> popup.setVisible(true));
|
||||
boolean isVisible1 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isVisible2 = popup.isVisible();
|
||||
|
||||
if (!isVisible1 || !isVisible2) {
|
||||
throw new RuntimeException("Expected result: popup is visible");
|
||||
}
|
||||
if (!isVisible1 || !isVisible2) {
|
||||
throw new RuntimeException("Expected result: popup is visible");
|
||||
}
|
||||
|
||||
System.out.println("Action: set the popup disabled");
|
||||
SwingUtilities.invokeAndWait(() -> popup.setEnabled(false));
|
||||
boolean isEnabled3 = popup.isEnabled();
|
||||
boolean isVisible3 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isEnabled4 = popup.isEnabled();
|
||||
boolean isVisible4 = popup.isVisible();
|
||||
if (isEnabled3 || isEnabled4) {
|
||||
throw new RuntimeException("Expected result: popup is disabled");
|
||||
}
|
||||
if (!isVisible3 || !isVisible4) {
|
||||
throw new RuntimeException("Expected result: disabled popup remains visible");
|
||||
}
|
||||
System.out.println("Action: set the popup disabled");
|
||||
SwingUtilities.invokeAndWait(() -> popup.setEnabled(false));
|
||||
boolean isEnabled3 = popup.isEnabled();
|
||||
boolean isVisible3 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isEnabled4 = popup.isEnabled();
|
||||
boolean isVisible4 = popup.isVisible();
|
||||
if (isEnabled3 || isEnabled4) {
|
||||
throw new RuntimeException("Expected result: popup is disabled");
|
||||
}
|
||||
if (!isVisible3 || !isVisible4) {
|
||||
throw new RuntimeException("Expected result: disabled popup remains visible");
|
||||
}
|
||||
|
||||
System.out.println("Action: set the popup invisible");
|
||||
SwingUtilities.invokeAndWait(() -> popup.setVisible(false));
|
||||
boolean isVisible5 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isVisible6 = popup.isVisible();
|
||||
if (isVisible5 && isVisible6) {
|
||||
throw new RuntimeException("Expected result: disabled popup remains visible");
|
||||
}
|
||||
System.out.println("Action: set the popup invisible");
|
||||
SwingUtilities.invokeAndWait(() -> popup.setVisible(false));
|
||||
boolean isVisible5 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isVisible6 = popup.isVisible();
|
||||
if (isVisible5 && isVisible6) {
|
||||
throw new RuntimeException("Expected result: disabled popup remains visible");
|
||||
}
|
||||
|
||||
System.out.println("Action: set popup enabled and visible");
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setVisible(true);
|
||||
popup.setEnabled(true);
|
||||
});
|
||||
boolean isEnabled7 = popup.isEnabled();
|
||||
boolean isVisible7 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isEnabled8 = popup.isEnabled();
|
||||
boolean isVisible8 = popup.isVisible();
|
||||
if (!isEnabled7 || !isEnabled8) {
|
||||
throw new RuntimeException("Expected result: popup is enabled");
|
||||
System.out.println("Action: set popup enabled and visible");
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setVisible(true);
|
||||
popup.setEnabled(true);
|
||||
});
|
||||
boolean isEnabled7 = popup.isEnabled();
|
||||
boolean isVisible7 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isEnabled8 = popup.isEnabled();
|
||||
boolean isVisible8 = popup.isVisible();
|
||||
if (!isEnabled7 || !isEnabled8) {
|
||||
throw new RuntimeException("Expected result: popup is enabled");
|
||||
}
|
||||
if (!isVisible7 || !isVisible8) {
|
||||
throw new RuntimeException("Expected result: popup becoming visible");
|
||||
}
|
||||
} finally {
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
if (!isVisible7 || !isVisible8) {
|
||||
throw new RuntimeException("Expected result: popup becoming visible");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
|
||||
private static void pause(Robot robot) {
|
||||
|
||||
@@ -55,7 +55,7 @@ java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemoni
|
||||
java/awt/KeyboardFocusmanager/TypeAhead/ButtonActionKeyTest/ButtonActionKeyTest.java 8257529,JBR-5397,JBR-7780 windows-x64,macosx-all,linux-all
|
||||
java/awt/KeyboardFocusmanager/TypeAhead/SubMenuShowTest/SubMenuShowTest.java JBR-5397,JBR-4074 macosx-all,windows-all
|
||||
java/awt/List/ItemEventTest/ItemEventTest.java JBR-5397,JBR-5505 macosx-all,windows-all
|
||||
java/awt/Modal/ModalFocusTransferTests/FocusTransferDWFAppModalTest.java JBR-5397 macosx-all
|
||||
java/awt/Modal/ModalFocusTransferTests/FocusTransferDWFAppModalTest.java JBR-5397,JBR-8074 macosx-all,windows-x64
|
||||
java/awt/Robot/ModifierRobotKey/ModifierRobotKeyTest.java JBR-5397,JBR-5802 macosx-all,windows-all
|
||||
java/awt/Toolkit/AWTEventListenerProxyTest/AWTEventListenerProxyTest.java JBR-6948 windows-x64
|
||||
java/awt/Toolkit/LockingKeyStateTest/LockingKeyStateTest.java JBR-5397 macosx-all
|
||||
@@ -128,6 +128,7 @@ java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java JBR-6857,JBR-5505 m
|
||||
java/awt/Choice/NonFocusablePopupMenuTest.java JBR-7961 windows-x64
|
||||
java/awt/Choice/RemoveAllShrinkTest/RemoveAllShrinkTest.java JBR-5510,8310487,JBR-6950 linux-5.18.2-arch1-1,linux-all,windows-x64
|
||||
java/awt/Choice/ResizeAutoClosesChoice/ResizeAutoClosesChoice.java JBR-5510,JBR-5905 linux-5.18.2-arch1-1,linux-all,windows-x64
|
||||
java/awt/ColorClass/AlphaColorTest.java JBR-7253 windows-x64
|
||||
java/awt/Component/NativeInLightShow/NativeInLightShow.java JBR-7715 windows-x64
|
||||
java/awt/Component/RepaintTest.java JBR-7754 windows-x64
|
||||
java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.java JBR-5538 windows-x64
|
||||
|
||||
@@ -47,6 +47,7 @@ javax/swing/JFileChooser/4400728/JFileChooserDefaultDirectoryTest.java initial_r
|
||||
javax/swing/JFileChooser/FileViewNPETest.java initial_runs generic-all
|
||||
javax/swing/JFormattedTextField/TestSelectedTextBackgroundColor.java initial_runs generic-all
|
||||
javax/swing/JFrame/JFrameBackgroundRefreshTest.java JBR-7471 linux-all
|
||||
javax/swing/JMenu/4213634/bug4213634.java JBR-8056 linux-aarch64
|
||||
javax/swing/JMenu/TestDisabledMenuForegroundColor.java initial_runs generic-all
|
||||
javax/swing/JPasswordField/TestSelectedTextBackgroundColor.java initial_runs generic-all
|
||||
javax/swing/JRadioButton/bug4823809.java JBR-7788 linux-all
|
||||
|
||||
@@ -260,7 +260,7 @@ java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java JBR-4275,JB
|
||||
java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java 7188711,8253184 linux-all,windows-all
|
||||
java/awt/FullScreen/UninitializedDisplayModeChangeTest/UninitializedDisplayModeChangeTest.java 7188711,8273617,JBR-4880,8253184 macosx-all,linux-all,windows-all
|
||||
java/awt/Focus/8013611/JDK8013611.java 8175366 windows-all,macosx-all
|
||||
java/awt/Focus/6401036/InputVerifierTest2.java JBR-7537 linux-aarch64
|
||||
java/awt/Focus/6401036/InputVerifierTest2.java JBR-7537 linux-all
|
||||
java/awt/Focus/6981400/Test1.java 8029675,JBR-5510 windows-all,macosx-all,linux-5.18.2-arch1-1
|
||||
java/awt/Focus/6981400/Test3.java 8173264 generic-all
|
||||
java/awt/Focus/8000326/SetFocusTraversalKeysEnabledTest.java JBR-4997,JBR-5729 windows-all,linux-all
|
||||
@@ -552,7 +552,7 @@ java/awt/Mouse/ExtraMouseClick/ExtraMouseClick.java 8253184,JBR-5709 windows-all
|
||||
java/awt/Mouse/MouseComboBoxTest/MouseComboBoxTest.java 8253184,JBR-6752 windows-all,linux-all
|
||||
java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java 8253184,JBR-6407 windows-all,linux-all
|
||||
java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Standard.java 7124407,8302787 macosx-all,windows-all
|
||||
java/awt/Mouse/RemovedComponentMouseListener/RemovedComponentMouseListener.java 8157170,8253184 macosx-all,windows-all
|
||||
java/awt/Mouse/RemovedComponentMouseListener/RemovedComponentMouseListener.java 8157170,8253184,JBR-8127 macosx-all,windows-all,linux-5.15.0-1075-aws
|
||||
java/awt/MouseAdapter/MouseAdapterUnitTest/MouseAdapterUnitTest.java 8253184 windows-all
|
||||
java/awt/MouseInfo/ComponentMousePositionTest.java 8253184 windows-all
|
||||
java/awt/MouseInfo/JContainerMousePositionTest.java 8253184 windows-all
|
||||
@@ -1316,7 +1316,7 @@ java/awt/Frame/MiscUndecorated/UndecoratedInitiallyIconified.java JBR-4880 windo
|
||||
java/awt/FullScreen/SetFSWindow/FSFrame.java 8253184 windows-all
|
||||
java/awt/grab/MenuDragEvents/MenuDragEvents.java JBR-4880 windows-all
|
||||
java/awt/image/mlib/MlibOpsTest.java JBR-5225 windows-all,windows-aarch64
|
||||
java/awt/MenuBar/SeparatorsNavigation/SeparatorsNavigation.java JBR-4880 windows-all
|
||||
java/awt/MenuBar/SeparatorsNavigation/SeparatorsNavigation.java JBR-4880,JBR-8090 windows-all,linux-5.18.2-arch1-1
|
||||
javax/swing/JFileChooser/8002077/bug8002077.java JBR-4880 windows-all
|
||||
javax/swing/JFileChooser/JFileChooserSetLocationTest.java 8295804 linux-all,macosx-all,windows-all
|
||||
javax/swing/JSlider/6348946/bug6348946.java 8197552,JBR-5387 windows-all,linux-all
|
||||
|
||||
@@ -88,7 +88,13 @@ java/awt/Robot/HiDPIScreenCapture/HiDPIRobotScreenCaptureTest.java
|
||||
java/awt/Window/MultiWindowApp/ChildAlwaysOnTopTest.java nobug generic-all
|
||||
javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java nobug generic-all
|
||||
javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedTranslucentPerPixelTranslucentGradient.java nobug generic-all
|
||||
javax/swing/plaf/metal/MetalBorders/ScaledMetalBorderTest.java nobug generic-all
|
||||
javax/swing/plaf/metal/MetalBorders/ScaledMetalBorderTest.java#id0 nobug macosx-all,linux-all,windows-all
|
||||
javax/swing/plaf/metal/MetalBorders/ScaledMetalBorderTest.java#id1 nobug macosx-all,linux-all,windows-all
|
||||
javax/swing/plaf/metal/MetalBorders/ScaledMetalBorderTest.java#id2 nobug windows-all
|
||||
javax/swing/plaf/metal/MetalBorders/ScaledMetalBorderTest.java#id3 nobug windows-all
|
||||
javax/swing/plaf/metal/MetalBorders/ScaledMetalBorderTest.java#id4 nobug windows-all
|
||||
javax/swing/plaf/metal/MetalBorders/ScaledMetalBorderTest.java#id5 nobug windows-all
|
||||
javax/swing/plaf/metal/MetalBorders/ScaledMetalBorderTest.java#id6 nobug windows-all
|
||||
jb/java/awt/CustomTitleBar/ActionListenerTest.java nobug generic-all
|
||||
jb/java/awt/CustomTitleBar/ChangeTitleBarHeightTest.java nobug generic-all
|
||||
jb/java/awt/CustomTitleBar/CheckFullScreen.java nobug generic-all
|
||||
|
||||
@@ -45,8 +45,8 @@ import jdk.test.lib.RandomFactory;
|
||||
* @library /test/lib
|
||||
* @build TestMaxCachedBufferSize
|
||||
* @run main/othervm/timeout=150 TestMaxCachedBufferSize
|
||||
* @run main/othervm/timeout=150 -Djdk.nio.maxCachedBufferSize=0 TestMaxCachedBufferSize
|
||||
* @run main/othervm/timeout=150 -Djdk.nio.maxCachedBufferSize=2000 TestMaxCachedBufferSize
|
||||
* @run main/othervm/timeout=150 -Djbr.java.io.use.nio=false -Djdk.nio.maxCachedBufferSize=0 TestMaxCachedBufferSize
|
||||
* @run main/othervm/timeout=150 -Djbr.java.io.use.nio=false -Djdk.nio.maxCachedBufferSize=2000 TestMaxCachedBufferSize
|
||||
* @run main/othervm/timeout=150 -Djdk.nio.maxCachedBufferSize=100000 TestMaxCachedBufferSize
|
||||
* @run main/othervm/timeout=150 -Djdk.nio.maxCachedBufferSize=10000000 TestMaxCachedBufferSize
|
||||
* @summary Test the implementation of the jdk.nio.maxCachedBufferSize property
|
||||
|
||||
Reference in New Issue
Block a user