Fix FileAccess for good, add new 2 verify methods
This commit is contained in:
parent
32816ecce1
commit
c13eaead94
1 changed files with 126 additions and 31 deletions
|
@ -357,7 +357,7 @@ class FileAccess {
|
||||||
*/
|
*/
|
||||||
@Throws(IOAccessException::class)
|
@Throws(IOAccessException::class)
|
||||||
fun getType(): Type {
|
fun getType(): Type {
|
||||||
return if (!exists()) Type.VOID
|
return if (!exists(noFollowSymbolicLink = true)) Type.VOID
|
||||||
else if (Files.isRegularFile(path)) Type.FILE
|
else if (Files.isRegularFile(path)) Type.FILE
|
||||||
else if (Files.isDirectory(path)) Type.DIRECTORY
|
else if (Files.isDirectory(path)) Type.DIRECTORY
|
||||||
else Type.UNKNOWN
|
else Type.UNKNOWN
|
||||||
|
@ -566,7 +566,7 @@ class FileAccess {
|
||||||
*/
|
*/
|
||||||
@Throws(IOAccessException::class)
|
@Throws(IOAccessException::class)
|
||||||
fun createFile(): FileAccess {
|
fun createFile(): FileAccess {
|
||||||
if (!exists())
|
if (!exists(noFollowSymbolicLink = true))
|
||||||
try {
|
try {
|
||||||
logger.diag("Creating a file at '${unformatFromPath(path)}'")
|
logger.diag("Creating a file at '${unformatFromPath(path)}'")
|
||||||
file.parentFile.mkdirs()
|
file.parentFile.mkdirs()
|
||||||
|
@ -591,7 +591,7 @@ class FileAccess {
|
||||||
*/
|
*/
|
||||||
@Throws(IOAccessException::class)
|
@Throws(IOAccessException::class)
|
||||||
fun createDirectory(): FileAccess {
|
fun createDirectory(): FileAccess {
|
||||||
if (!exists())
|
if (!exists(noFollowSymbolicLink = true))
|
||||||
try {
|
try {
|
||||||
logger.diag("Creating a directory at '${unformatFromPath(path)}'")
|
logger.diag("Creating a directory at '${unformatFromPath(path)}'")
|
||||||
file.mkdirs()
|
file.mkdirs()
|
||||||
|
@ -619,7 +619,7 @@ class FileAccess {
|
||||||
*/
|
*/
|
||||||
@Throws(IOAccessException::class)
|
@Throws(IOAccessException::class)
|
||||||
fun createLink(destination: FileAccess, hard: Boolean): FileAccess {
|
fun createLink(destination: FileAccess, hard: Boolean): FileAccess {
|
||||||
if (!exists())
|
if (!exists(noFollowSymbolicLink = true))
|
||||||
try {
|
try {
|
||||||
logger.diag("Creating a ${if (hard) "hard" else "symbolic"} link at '${unformatFromPath(path)}'")
|
logger.diag("Creating a ${if (hard) "hard" else "symbolic"} link at '${unformatFromPath(path)}'")
|
||||||
if (hard) Files.createLink(path, destination.path)
|
if (hard) Files.createLink(path, destination.path)
|
||||||
|
@ -707,7 +707,7 @@ class FileAccess {
|
||||||
*/
|
*/
|
||||||
@Throws(IOAccessException::class)
|
@Throws(IOAccessException::class)
|
||||||
fun delete(): FileAccess {
|
fun delete(): FileAccess {
|
||||||
if (exists())
|
if (exists(noFollowSymbolicLink = true))
|
||||||
try {
|
try {
|
||||||
logger.diag("Deleting '${unformatFromPath(path)}'")
|
logger.diag("Deleting '${unformatFromPath(path)}'")
|
||||||
|
|
||||||
|
@ -825,12 +825,17 @@ class FileAccess {
|
||||||
@Throws(IOAccessException::class)
|
@Throws(IOAccessException::class)
|
||||||
fun writeBytes(bytes: ByteArray, async: Boolean = false): FileAccess {
|
fun writeBytes(bytes: ByteArray, async: Boolean = false): FileAccess {
|
||||||
try {
|
try {
|
||||||
if (getType() != Type.FILE)
|
when (getType()) {
|
||||||
return this
|
Type.UNKNOWN, Type.DIRECTORY -> return this
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
|
||||||
logger.diag("Writing to file '${path}' (bytes, ${if (async) "async" else ""})")
|
logger.diag("Writing to file '${path}' (bytes, ${if (async) "async" else ""})")
|
||||||
createFile()
|
createFile()
|
||||||
Files.write(path, bytes, StandardOpenOption.WRITE, if (async) StandardOpenOption.DSYNC else StandardOpenOption.SYNC)
|
if (async)
|
||||||
|
Files.write(path, bytes, StandardOpenOption.WRITE)
|
||||||
|
else
|
||||||
|
Files.write(path, bytes, StandardOpenOption.WRITE, StandardOpenOption.SYNC)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
throw IOAccessException("Unable to read file '${path}' (bytes, ${if (async) "async" else ""})", exception)
|
throw IOAccessException("Unable to read file '${path}' (bytes, ${if (async) "async" else ""})", exception)
|
||||||
}
|
}
|
||||||
|
@ -855,12 +860,17 @@ class FileAccess {
|
||||||
@Throws(IOAccessException::class)
|
@Throws(IOAccessException::class)
|
||||||
fun writeLines(lines: List<String>, async: Boolean = false): FileAccess {
|
fun writeLines(lines: List<String>, async: Boolean = false): FileAccess {
|
||||||
try {
|
try {
|
||||||
if (getType() != Type.FILE)
|
when (getType()) {
|
||||||
return this
|
Type.UNKNOWN, Type.DIRECTORY -> return this
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
|
||||||
logger.diag("Writing to file '${path}' (lines, ${if (async) "async" else ""})")
|
logger.diag("Writing to file '${path}' (lines, ${if (async) "async" else ""})")
|
||||||
createFile()
|
createFile()
|
||||||
Files.write(path, lines, StandardOpenOption.WRITE, if (async) StandardOpenOption.DSYNC else StandardOpenOption.SYNC)
|
if (async)
|
||||||
|
Files.write(path, lines, StandardOpenOption.WRITE)
|
||||||
|
else
|
||||||
|
Files.write(path, lines, StandardOpenOption.WRITE, StandardOpenOption.SYNC)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
throw IOAccessException("Unable to read file '${path}' (lines, ${if (async) "async" else ""})", exception)
|
throw IOAccessException("Unable to read file '${path}' (lines, ${if (async) "async" else ""})", exception)
|
||||||
}
|
}
|
||||||
|
@ -885,12 +895,17 @@ class FileAccess {
|
||||||
@Throws(IOAccessException::class)
|
@Throws(IOAccessException::class)
|
||||||
fun writeString(string: String, async: Boolean = false): FileAccess {
|
fun writeString(string: String, async: Boolean = false): FileAccess {
|
||||||
try {
|
try {
|
||||||
if (getType() != Type.FILE)
|
when (getType()) {
|
||||||
return this
|
Type.UNKNOWN, Type.DIRECTORY -> return this
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
|
||||||
logger.diag("Writing to file '${path}' (string, ${if (async) "async" else ""})")
|
logger.diag("Writing to file '${path}' (string, ${if (async) "async" else ""})")
|
||||||
createFile()
|
createFile()
|
||||||
Files.writeString(path, string, StandardOpenOption.WRITE, if (async) StandardOpenOption.DSYNC else StandardOpenOption.SYNC)
|
if (async)
|
||||||
|
Files.writeString(path, string, StandardOpenOption.WRITE)
|
||||||
|
else
|
||||||
|
Files.writeString(path, string, StandardOpenOption.WRITE, StandardOpenOption.SYNC)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
throw IOAccessException("Unable to read file '${path}' (string, ${if (async) "async" else ""})", exception)
|
throw IOAccessException("Unable to read file '${path}' (string, ${if (async) "async" else ""})", exception)
|
||||||
}
|
}
|
||||||
|
@ -915,12 +930,17 @@ class FileAccess {
|
||||||
@Throws(IOAccessException::class)
|
@Throws(IOAccessException::class)
|
||||||
fun appendBytes(bytes: ByteArray, async: Boolean = false): FileAccess {
|
fun appendBytes(bytes: ByteArray, async: Boolean = false): FileAccess {
|
||||||
try {
|
try {
|
||||||
if (getType() != Type.FILE)
|
when (getType()) {
|
||||||
return this
|
Type.UNKNOWN, Type.DIRECTORY -> return this
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
|
||||||
logger.diag("Appending to file '${path}' (bytes, ${if (async) "async" else ""})")
|
logger.diag("Appending to file '${path}' (bytes, ${if (async) "async" else ""})")
|
||||||
createFile()
|
createFile()
|
||||||
Files.write(path, bytes, StandardOpenOption.APPEND, if (async) StandardOpenOption.DSYNC else StandardOpenOption.SYNC)
|
if (async)
|
||||||
|
Files.write(path, bytes, StandardOpenOption.APPEND)
|
||||||
|
else
|
||||||
|
Files.write(path, bytes, StandardOpenOption.APPEND, StandardOpenOption.SYNC)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
throw IOAccessException("Unable to read file '${path}' (bytes, ${if (async) "async" else ""})", exception)
|
throw IOAccessException("Unable to read file '${path}' (bytes, ${if (async) "async" else ""})", exception)
|
||||||
}
|
}
|
||||||
|
@ -945,12 +965,17 @@ class FileAccess {
|
||||||
@Throws(IOAccessException::class)
|
@Throws(IOAccessException::class)
|
||||||
fun appendLines(lines: List<String>, async: Boolean = false): FileAccess {
|
fun appendLines(lines: List<String>, async: Boolean = false): FileAccess {
|
||||||
try {
|
try {
|
||||||
if (getType() != Type.FILE)
|
when (getType()) {
|
||||||
return this
|
Type.UNKNOWN, Type.DIRECTORY -> return this
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
|
||||||
logger.diag("Appending to file '${path}' (lines, ${if (async) "async" else ""})")
|
logger.diag("Appending to file '${path}' (lines, ${if (async) "async" else ""})")
|
||||||
createFile()
|
createFile()
|
||||||
Files.write(path, lines, StandardOpenOption.APPEND, if (async) StandardOpenOption.DSYNC else StandardOpenOption.SYNC)
|
if (async)
|
||||||
|
Files.write(path, lines, StandardOpenOption.APPEND)
|
||||||
|
else
|
||||||
|
Files.write(path, lines, StandardOpenOption.APPEND, StandardOpenOption.SYNC)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
throw IOAccessException("Unable to read file '${path}' (lines, ${if (async) "async" else ""})", exception)
|
throw IOAccessException("Unable to read file '${path}' (lines, ${if (async) "async" else ""})", exception)
|
||||||
}
|
}
|
||||||
|
@ -975,12 +1000,17 @@ class FileAccess {
|
||||||
@Throws(IOAccessException::class)
|
@Throws(IOAccessException::class)
|
||||||
fun appendString(string: String, async: Boolean = false): FileAccess {
|
fun appendString(string: String, async: Boolean = false): FileAccess {
|
||||||
try {
|
try {
|
||||||
if (getType() != Type.FILE)
|
when (getType()) {
|
||||||
return this
|
Type.UNKNOWN, Type.DIRECTORY -> return this
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
|
||||||
logger.diag("Appending to file '${path}' (string, ${if (async) "async" else ""})")
|
logger.diag("Appending to file '${path}' (string, ${if (async) "async" else ""})")
|
||||||
createFile()
|
createFile()
|
||||||
Files.writeString(path, string, StandardOpenOption.APPEND, if (async) StandardOpenOption.DSYNC else StandardOpenOption.SYNC)
|
if (async)
|
||||||
|
Files.writeString(path, string, StandardOpenOption.APPEND)
|
||||||
|
else
|
||||||
|
Files.writeString(path, string, StandardOpenOption.APPEND, StandardOpenOption.SYNC)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
throw IOAccessException("Unable to read file '${path}' (string, ${if (async) "async" else ""})", exception)
|
throw IOAccessException("Unable to read file '${path}' (string, ${if (async) "async" else ""})", exception)
|
||||||
}
|
}
|
||||||
|
@ -1105,14 +1135,21 @@ class FileAccess {
|
||||||
* Verifies that something
|
* Verifies that something
|
||||||
* exists at this location.
|
* exists at this location.
|
||||||
*
|
*
|
||||||
|
* This method does not follow symbolic links
|
||||||
|
* and instead looks at the file directly. This
|
||||||
|
* method should likely be used to check if
|
||||||
|
* something exists at that exact location.
|
||||||
|
* In case you may need to follow symbolic links,
|
||||||
|
* use [verifyExistsLink] instead.
|
||||||
|
*
|
||||||
* @return this instance
|
* @return this instance
|
||||||
* @throws IOAccessException on IO error
|
* @throws IOAccessException on IO error
|
||||||
* @throws VerificationFailedException if the verification fails
|
* @throws VerificationFailedException if the verification fails
|
||||||
* @since v1-alpha10
|
* @since v1-alpha10
|
||||||
*/
|
*/
|
||||||
@Throws(IOAccessException::class, VerificationFailedException::class)
|
@Throws(IOAccessException::class, VerificationFailedException::class)
|
||||||
fun verifyExists(noFollowSymbolicLink: Boolean = false): FileAccess {
|
fun verifyExists(): FileAccess {
|
||||||
if (!exists(noFollowSymbolicLink = noFollowSymbolicLink))
|
if (!exists(noFollowSymbolicLink = true))
|
||||||
throw VerificationFailedException("Expected that something exists at '${unformatFromPath(path)}'")
|
throw VerificationFailedException("Expected that something exists at '${unformatFromPath(path)}'")
|
||||||
|
|
||||||
return this
|
return this
|
||||||
|
@ -1122,19 +1159,76 @@ class FileAccess {
|
||||||
* Verifies that something does
|
* Verifies that something does
|
||||||
* not exist at this location.
|
* not exist at this location.
|
||||||
*
|
*
|
||||||
|
* This method does not follow symbolic links
|
||||||
|
* and instead looks at the file directly. This
|
||||||
|
* method should likely be used to check if
|
||||||
|
* something exists at that exact location.
|
||||||
|
* In case you may need to follow symbolic links,
|
||||||
|
* use [verifyNotExistsLink] instead.
|
||||||
|
*
|
||||||
* @return this instance
|
* @return this instance
|
||||||
* @throws IOAccessException on IO error
|
* @throws IOAccessException on IO error
|
||||||
* @throws VerificationFailedException if the verification fails
|
* @throws VerificationFailedException if the verification fails
|
||||||
* @since v1-alpha10
|
* @since v1-alpha10
|
||||||
*/
|
*/
|
||||||
@Throws(IOAccessException::class, VerificationFailedException::class)
|
@Throws(IOAccessException::class, VerificationFailedException::class)
|
||||||
fun verifyNotExists(noFollowSymbolicLink: Boolean = false): FileAccess {
|
fun verifyNotExists(): FileAccess {
|
||||||
if (exists(noFollowSymbolicLink = noFollowSymbolicLink))
|
if (exists(noFollowSymbolicLink = true))
|
||||||
throw VerificationFailedException("Expected that nothing exists at '${unformatFromPath(path)}'")
|
throw VerificationFailedException("Expected that nothing exists at '${unformatFromPath(path)}'")
|
||||||
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that something
|
||||||
|
* exists at this location.
|
||||||
|
*
|
||||||
|
* This method follows symbolic links during
|
||||||
|
* the verification process, which should
|
||||||
|
* only be used to check if you can read/write
|
||||||
|
* from a file. In case you need to verify the
|
||||||
|
* existence of this very file and do not
|
||||||
|
* require following symbolic links, use the
|
||||||
|
* [verifyNotExists] method instead.
|
||||||
|
*
|
||||||
|
* @return this instance
|
||||||
|
* @throws IOAccessException on IO error
|
||||||
|
* @throws VerificationFailedException if the verification fails
|
||||||
|
* @since v1-alpha10
|
||||||
|
*/
|
||||||
|
@Throws(IOAccessException::class, VerificationFailedException::class)
|
||||||
|
fun verifyExistsLink(): FileAccess {
|
||||||
|
if (!exists(noFollowSymbolicLink = false))
|
||||||
|
throw VerificationFailedException("Expected the link destination of '${unformatFromPath(path)}' is dead")
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that something does
|
||||||
|
* not exist at this location.
|
||||||
|
*
|
||||||
|
* This method follows symbolic links during
|
||||||
|
* the verification process, which should
|
||||||
|
* only be used to check if you can read/write
|
||||||
|
* from a file. In case you need to verify the
|
||||||
|
* existence of this very file and do not
|
||||||
|
* require following symbolic links, use the
|
||||||
|
* [verifyExists] method instead.
|
||||||
|
*
|
||||||
|
* @return this instance
|
||||||
|
* @throws IOAccessException on IO error
|
||||||
|
* @throws VerificationFailedException if the verification fails
|
||||||
|
* @since v1-alpha10
|
||||||
|
*/
|
||||||
|
@Throws(IOAccessException::class, VerificationFailedException::class)
|
||||||
|
fun verifyNotExistsLink(): FileAccess {
|
||||||
|
if (exists(noFollowSymbolicLink = false))
|
||||||
|
throw VerificationFailedException("Expected that the link destination of '${unformatFromPath(path)}' exists")
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies that a file
|
* Verifies that a file
|
||||||
* is at this location.
|
* is at this location.
|
||||||
|
@ -1214,7 +1308,7 @@ class FileAccess {
|
||||||
*/
|
*/
|
||||||
@Throws(IOAccessException::class, VerificationFailedException::class)
|
@Throws(IOAccessException::class, VerificationFailedException::class)
|
||||||
fun verifyIsLink(): FileAccess {
|
fun verifyIsLink(): FileAccess {
|
||||||
if (exists() && isSymbolicLink())
|
if (exists(noFollowSymbolicLink = true) && isSymbolicLink())
|
||||||
throw VerificationFailedException("Expected that '${unformatFromPath(path)}' is a link")
|
throw VerificationFailedException("Expected that '${unformatFromPath(path)}' is a link")
|
||||||
|
|
||||||
return this
|
return this
|
||||||
|
@ -1231,7 +1325,7 @@ class FileAccess {
|
||||||
*/
|
*/
|
||||||
@Throws(IOAccessException::class, VerificationFailedException::class)
|
@Throws(IOAccessException::class, VerificationFailedException::class)
|
||||||
fun verifyIsNotLink(): FileAccess {
|
fun verifyIsNotLink(): FileAccess {
|
||||||
if (exists() && !isSymbolicLink())
|
if (exists(noFollowSymbolicLink = true) && !isSymbolicLink())
|
||||||
throw VerificationFailedException("Expected that '${unformatFromPath(path)}' is not a link")
|
throw VerificationFailedException("Expected that '${unformatFromPath(path)}' is not a link")
|
||||||
|
|
||||||
return this
|
return this
|
||||||
|
@ -1248,7 +1342,7 @@ class FileAccess {
|
||||||
*/
|
*/
|
||||||
@Throws(IOAccessException::class, VerificationFailedException::class)
|
@Throws(IOAccessException::class, VerificationFailedException::class)
|
||||||
fun verifyIsValidLink(): FileAccess {
|
fun verifyIsValidLink(): FileAccess {
|
||||||
if (exists() && (isSymbolicLink() || getLinkDestination() != null))
|
if (exists(noFollowSymbolicLink = true) && (isSymbolicLink() || getLinkDestination() != null))
|
||||||
throw VerificationFailedException("Expected that '${unformatFromPath(path)}' is a link")
|
throw VerificationFailedException("Expected that '${unformatFromPath(path)}' is a link")
|
||||||
|
|
||||||
return this
|
return this
|
||||||
|
@ -1265,7 +1359,7 @@ class FileAccess {
|
||||||
*/
|
*/
|
||||||
@Throws(IOAccessException::class, VerificationFailedException::class)
|
@Throws(IOAccessException::class, VerificationFailedException::class)
|
||||||
fun verifyIsNotValidLink(): FileAccess {
|
fun verifyIsNotValidLink(): FileAccess {
|
||||||
if (exists() && !(isSymbolicLink() || getLinkDestination() != null))
|
if (exists(noFollowSymbolicLink = true) && !(isSymbolicLink() || getLinkDestination() != null))
|
||||||
throw VerificationFailedException("Expected that '${unformatFromPath(path)}' is not a link")
|
throw VerificationFailedException("Expected that '${unformatFromPath(path)}' is not a link")
|
||||||
|
|
||||||
return this
|
return this
|
||||||
|
@ -1387,6 +1481,7 @@ class FileAccess {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFile(path: Path, attributes: BasicFileAttributes): FileVisitResult {
|
override fun visitFile(path: Path, attributes: BasicFileAttributes): FileVisitResult {
|
||||||
|
path.toFile().delete()
|
||||||
return FileVisitResult.CONTINUE
|
return FileVisitResult.CONTINUE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue