Fix directory handling, add more content listing methods
Some checks failed
build-and-test / build (push) Failing after 1m34s
build-and-test / generate-javadoc (push) Failing after 1m36s
build-and-test / test (push) Failing after 1m34s

This commit is contained in:
JeremyStar™ 2024-12-04 01:01:17 +01:00
parent a7c02cc9c2
commit a392e8eb48
Signed by: JeremyStarTM
GPG key ID: E366BAEF67E4704D

View file

@ -26,6 +26,7 @@ import de.staropensource.engine.base.utility.misc.Miscellaneous;
import lombok.Getter; import lombok.Getter;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -34,6 +35,7 @@ import java.net.URI;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.*; import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.PosixFilePermissions; import java.nio.file.attribute.PosixFilePermissions;
import java.util.*; import java.util.*;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -410,7 +412,7 @@ public final class FileAccess {
* @throws IOException on an IO error * @throws IOException on an IO error
* @since v1-alpha8 * @since v1-alpha8
*/ */
public @NotNull String @NotNull [] listContents() throws UnsupportedOperationException, IOException { public @NotNull String @NotNull [] list() throws UnsupportedOperationException, IOException {
if (getType() != Type.DIRECTORY) if (getType() != Type.DIRECTORY)
throw new UnsupportedOperationException("The file '" + path + "' is not a directory"); throw new UnsupportedOperationException("The file '" + path + "' is not a directory");
@ -422,6 +424,58 @@ public final class FileAccess {
return list; return list;
} }
/**
* Returns the names of all files
* in this directory.
*
* @return array of file names
* @throws UnsupportedOperationException if this file isn't a directory
* @throws IOException on an IO error
* @since v1-alpha8
*/
public @NotNull String @NotNull [] listFiles() throws UnsupportedOperationException, IOException {
if (getType() != Type.DIRECTORY)
throw new UnsupportedOperationException("The file '" + path + "' is not a directory");
String[] listArray = file.list();
List<@NotNull String> list = new ArrayList<>();
if (listArray == null)
throw new IOException("list is null (isn't a directory although it should be one)");
for (String item : listArray)
if (path.resolve(item).toFile().isFile())
list.add(item);
return list.toArray(new String[0]);
}
/**
* Returns the names of all
* directories in this directory.
*
* @return array of directory names
* @throws UnsupportedOperationException if this file isn't a directory
* @throws IOException on an IO error
* @since v1-alpha8
*/
public @NotNull String @NotNull [] listDirectories() throws UnsupportedOperationException, IOException {
if (getType() != Type.DIRECTORY)
throw new UnsupportedOperationException("The file '" + path + "' is not a directory");
String[] listArray = file.list();
List<@NotNull String> list = new ArrayList<>();
if (listArray == null)
throw new IOException("list is null (isn't a directory although it should be one)");
for (String item : listArray)
if (path.resolve(item).toFile().isDirectory())
list.add(item);
return list.toArray(new String[0]);
}
/** /**
* Returns the destination of the symbolic link. * Returns the destination of the symbolic link.
* *
@ -699,6 +753,7 @@ public final class FileAccess {
* @since v1-alpha9 * @since v1-alpha9
*/ */
public @NotNull FileAccess move(@NotNull FileAccess destination) throws IOException { public @NotNull FileAccess move(@NotNull FileAccess destination) throws IOException {
Logger.diag("Moving '" + path + "' to '" + destination.path + "'");
Files.move(path, destination.path, StandardCopyOption.REPLACE_EXISTING); Files.move(path, destination.path, StandardCopyOption.REPLACE_EXISTING);
return destination; return destination;
} }
@ -712,7 +767,11 @@ public final class FileAccess {
* @since v1-alpha9 * @since v1-alpha9
*/ */
public @NotNull FileAccess copy(@NotNull FileAccess destination) throws IOException { public @NotNull FileAccess copy(@NotNull FileAccess destination) throws IOException {
Files.copy(path, destination.path, StandardCopyOption.REPLACE_EXISTING); Logger.diag("Copying '" + path + "' to '" + destination.path + "'");
if (file.isDirectory())
Files.walkFileTree(path, new CopyDirectoryVisitor(path, destination.path));
else
Files.copy(path, destination.path, StandardCopyOption.REPLACE_EXISTING);
return this; return this;
} }
@ -721,11 +780,17 @@ public final class FileAccess {
* If it doesn't exist, nothing will be done. * If it doesn't exist, nothing will be done.
* *
* @return this instance * @return this instance
* @throws IOException on an IO error
* @since v1-alpha8 * @since v1-alpha8
*/ */
public @NotNull FileAccess delete() { public @NotNull FileAccess delete() throws IOException {
if (exists()) { if (exists()) {
Logger.diag("Deleting '" + path + "'"); Logger.diag("Deleting '" + path + "'");
// Recursively delete if directory
if (getFile().isDirectory())
Files.walkFileTree(path, new DeleteDirectoryVisitor(path));
//noinspection ResultOfMethodCallIgnored //noinspection ResultOfMethodCallIgnored
file.delete(); file.delete();
} }
@ -1013,4 +1078,93 @@ public final class FileAccess {
*/ */
UNKNOWN UNKNOWN
} }
/**
* {@link FileVisitor} instance for
* copying directories recursively.
*
* @param source source to copy from
* @param destination destination to copy to
* @since v1-alpha9
*/
private record CopyDirectoryVisitor(@NotNull Path source, @NotNull Path destination) implements FileVisitor<@NotNull Path> {
/**
* Creates and initializes an
* instance of this class.
*
* @since v1-alpha9
*/
private CopyDirectoryVisitor {}
@Override
public @NotNull FileVisitResult preVisitDirectory(Path path, @NotNull BasicFileAttributes attributes) throws IOException {
Files.createDirectories(destination.resolve(source.relativize(path)));
return FileVisitResult.CONTINUE;
}
/** {@inheritDoc} */
@Override
public @NotNull FileVisitResult visitFile(Path path, @NotNull BasicFileAttributes attributes) throws IOException {
Files.copy(path, destination.resolve(source.relativize(path)));
return FileVisitResult.CONTINUE;
}
/** {@inheritDoc} */
@Override
public @NotNull FileVisitResult visitFileFailed(Path path, @NotNull IOException exception) throws IOException {
throw exception;
}
/** {@inheritDoc} */
@Override
public @NotNull FileVisitResult postVisitDirectory(Path path, @Nullable IOException exception) throws IOException {
if (exception != null)
throw exception;
return FileVisitResult.CONTINUE;
}
}
/**
* {@link FileVisitor} instance for
* delete directories recursively.
*
* @param directory directory to delete
* @since v1-alpha9
*/
private record DeleteDirectoryVisitor(@NotNull Path directory) implements FileVisitor<@NotNull Path> {
/**
* Creates and initializes an
* instance of this class.
*
* @since v1-alpha9
*/
private DeleteDirectoryVisitor {}
@Override
public @NotNull FileVisitResult preVisitDirectory(Path path, @NotNull BasicFileAttributes attributes) {
return FileVisitResult.CONTINUE;
}
/** {@inheritDoc} */
@Override
public @NotNull FileVisitResult visitFile(Path path, @NotNull BasicFileAttributes attributes) throws IOException {
Files.delete(path);
return FileVisitResult.CONTINUE;
}
/** {@inheritDoc} */
@Override
public @NotNull FileVisitResult visitFileFailed(Path path, @NotNull IOException exception) throws IOException {
throw exception;
}
/** {@inheritDoc} */
@Override
public @NotNull FileVisitResult postVisitDirectory(Path path, @Nullable IOException exception) throws IOException {
if (exception != null)
throw exception;
Files.delete(path);
return FileVisitResult.CONTINUE;
}
}
} }