Migrate from java.io.File to java.nio.file.Path

This commit is contained in:
Syer10
2021-09-27 21:18:22 -04:00
parent 1a7b475439
commit b264452c75
8 changed files with 60 additions and 43 deletions

View File

@@ -11,12 +11,12 @@ import okio.BufferedSink
import okio.Source import okio.Source
import okio.buffer import okio.buffer
import okio.sink import okio.sink
import java.io.File import java.nio.file.Path
suspend fun Source.saveTo(file: File) { suspend fun Source.saveTo(path: Path) {
withIOContext { withIOContext {
use { source -> use { source ->
file.sink().buffer().use { it.writeAll(source) } path.sink().buffer().use { it.writeAll(source) }
} }
} }
} }

View File

@@ -16,7 +16,8 @@ import org.apache.logging.log4j.core.appender.ConsoleAppender
import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory
import org.slf4j.bridge.SLF4JBridgeHandler import org.slf4j.bridge.SLF4JBridgeHandler
import java.io.File import java.nio.file.Path
import kotlin.io.path.absolutePathString
import java.util.logging.LogManager as JLogManager import java.util.logging.LogManager as JLogManager
const val consolePattern = const val consolePattern =
@@ -37,7 +38,7 @@ const val filePattern =
"{LOG_EXCEPTION_CONVERSION_WORD:-%xEx}" "{LOG_EXCEPTION_CONVERSION_WORD:-%xEx}"
@Suppress("UPPER_BOUND_VIOLATED_WARNING") @Suppress("UPPER_BOUND_VIOLATED_WARNING")
fun initializeLogger(loggingLocation: File) { fun initializeLogger(loggingLocation: Path) {
val ctx = LogManager.getContext(false) as LoggerContext val ctx = LogManager.getContext(false) as LoggerContext
val builder = ConfigurationBuilderFactory.newConfigurationBuilder() val builder = ConfigurationBuilderFactory.newConfigurationBuilder()
.apply { .apply {
@@ -59,11 +60,11 @@ fun initializeLogger(loggingLocation: File) {
newAppender("Rolling", "RollingFile") newAppender("Rolling", "RollingFile")
.addAttribute( .addAttribute(
"fileName", "fileName",
loggingLocation.absolutePath.trimEnd { it == '/' || it == '\\' } + "/rolling.log" loggingLocation.absolutePathString().trimEnd { it == '/' || it == '\\' } + "/rolling.log"
) )
.addAttribute( .addAttribute(
"filePattern", "filePattern",
loggingLocation.absolutePath.trimEnd { it == '/' || it == '\\' } + "/archive/rolling-%d{yyyy-MM-dd-}.log.gz" loggingLocation.absolutePathString().trimEnd { it == '/' || it == '\\' } + "/archive/rolling-%d{yyyy-MM-dd-}.log.gz"
) )
.add( .add(
newLayout("PatternLayout") newLayout("PatternLayout")

View File

@@ -21,13 +21,22 @@ import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import mu.KotlinLogging import mu.KotlinLogging
import java.io.File import java.io.File.pathSeparatorChar
import java.io.IOException import java.io.IOException
import java.io.Reader import java.io.Reader
import java.nio.file.Path
import java.util.jar.Attributes import java.util.jar.Attributes
import java.util.jar.JarInputStream import java.util.jar.JarInputStream
import javax.inject.Inject import javax.inject.Inject
import kotlin.concurrent.thread import kotlin.concurrent.thread
import kotlin.io.path.Path
import kotlin.io.path.absolutePathString
import kotlin.io.path.createDirectories
import kotlin.io.path.exists
import kotlin.io.path.inputStream
import kotlin.io.path.isExecutable
import kotlin.io.path.name
import kotlin.io.path.outputStream
@OptIn(DelicateCoroutinesApi::class) @OptIn(DelicateCoroutinesApi::class)
class ServerService @Inject constructor( class ServerService @Inject constructor(
@@ -55,7 +64,7 @@ class ServerService @Inject constructor(
} }
@Throws(IOException::class) @Throws(IOException::class)
private fun copyJar(jarFile: File) { private fun copyJar(jarFile: Path) {
javaClass.getResourceAsStream("/Tachidesk.jar")?.buffered()?.use { input -> javaClass.getResourceAsStream("/Tachidesk.jar")?.buffered()?.use { input ->
jarFile.outputStream().use { output -> jarFile.outputStream().use { output ->
input.copyTo(output) input.copyTo(output)
@@ -63,30 +72,30 @@ class ServerService @Inject constructor(
} }
} }
private fun getJavaFromPath(javaPath: File): String? { private fun getJavaFromPath(javaPath: Path): String? {
val javaExeFile = File(javaPath, "java.exe") val javaExeFile = javaPath.resolve("java.exe")
val javaUnixFile = File(javaPath, "java") val javaUnixFile = javaPath.resolve("java")
return when { return when {
javaExeFile.exists() && javaExeFile.canExecute() -> javaExeFile.absolutePath javaExeFile.exists() && javaExeFile.isExecutable() -> javaExeFile.absolutePathString()
javaUnixFile.exists() && javaUnixFile.canExecute() -> javaUnixFile.absolutePath javaUnixFile.exists() && javaUnixFile.isExecutable() -> javaUnixFile.absolutePathString()
else -> null else -> null
} }
} }
private fun getRuntimeJava(): String? { private fun getRuntimeJava(): String? {
return System.getProperty("java.home")?.let { getJavaFromPath(File(it, "bin")) } return System.getProperty("java.home")?.let { getJavaFromPath(Path(it).resolve("bin")) }
} }
private fun getPossibleJava(): String? { private fun getPossibleJava(): String? {
return System.getProperty("java.library.path")?.split(File.pathSeparatorChar) return System.getProperty("java.library.path")?.split(pathSeparatorChar)
.orEmpty() .orEmpty()
.asSequence() .asSequence()
.mapNotNull { .mapNotNull {
val file = File(it) val file = Path(it)
if (file.absolutePath.contains("java") || file.absolutePath.contains("jdk")) { if (file.absolutePathString().contains("java") || file.absolutePathString().contains("jdk")) {
if (file.name.equals("bin", true)) { if (file.name.equals("bin", true)) {
file file
} else File(file, "bin") } else file.resolve("bin")
} else null } else null
} }
.mapNotNull { getJavaFromPath(it) } .mapNotNull { getJavaFromPath(it) }
@@ -117,7 +126,7 @@ class ServerService @Inject constructor(
} }
} }
GlobalScope.launch(handler) { GlobalScope.launch(handler) {
val jarFile = File(userDataDir.also { it.mkdirs() }, "Tachidesk.jar") val jarFile = userDataDir.also { it.createDirectories() }.resolve("Tachidesk.jar")
if (!jarFile.exists()) { if (!jarFile.exists()) {
info { "Copying server to resources" } info { "Copying server to resources" }
withIOContext { copyJar(jarFile) } withIOContext { copyJar(jarFile) }
@@ -147,7 +156,7 @@ class ServerService @Inject constructor(
withIOContext { withIOContext {
val reader: Reader val reader: Reader
process = ProcessBuilder(javaPath, *properties, "-jar", jarFile.absolutePath) process = ProcessBuilder(javaPath, *properties, "-jar", jarFile.absolutePathString())
.redirectErrorStream(true) .redirectErrorStream(true)
.start() .start()
.also { .also {

View File

@@ -21,15 +21,16 @@ import io.ktor.client.statement.HttpResponse
import io.ktor.http.ContentType import io.ktor.http.ContentType
import io.ktor.http.Headers import io.ktor.http.Headers
import io.ktor.http.HttpHeaders import io.ktor.http.HttpHeaders
import java.io.File import java.nio.file.Path
import javax.inject.Inject import javax.inject.Inject
import kotlin.io.path.readBytes
class BackupInteractionHandler @Inject constructor( class BackupInteractionHandler @Inject constructor(
client: Http, client: Http,
serverPreferences: ServerPreferences serverPreferences: ServerPreferences
) : BaseInteractionHandler(client, serverPreferences) { ) : BaseInteractionHandler(client, serverPreferences) {
suspend fun importBackupFile(file: File, block: HttpRequestBuilder.() -> Unit = {}) = withIOContext { suspend fun importBackupFile(file: Path, block: HttpRequestBuilder.() -> Unit = {}) = withIOContext {
client.submitFormWithBinaryData<HttpResponse>( client.submitFormWithBinaryData<HttpResponse>(
serverUrl + backupFileImportRequest(), serverUrl + backupFileImportRequest(),
formData = formData { formData = formData {
@@ -45,7 +46,7 @@ class BackupInteractionHandler @Inject constructor(
) )
} }
suspend fun validateBackupFile(file: File, block: HttpRequestBuilder.() -> Unit = {}) = withIOContext { suspend fun validateBackupFile(file: Path, block: HttpRequestBuilder.() -> Unit = {}) = withIOContext {
client.submitFormWithBinaryData<BackupValidationResult>( client.submitFormWithBinaryData<BackupValidationResult>(
serverUrl + validateBackupFileRequest(), serverUrl + validateBackupFileRequest(),
formData = formData { formData = formData {

View File

@@ -52,13 +52,12 @@ import org.jetbrains.skiko.currentSystemTheme
import toothpick.configuration.Configuration import toothpick.configuration.Configuration
import toothpick.ktp.KTP import toothpick.ktp.KTP
import toothpick.ktp.extension.getInstance import toothpick.ktp.extension.getInstance
import java.io.File
import java.util.Locale import java.util.Locale
import kotlin.system.exitProcess import kotlin.system.exitProcess
@OptIn(DelicateCoroutinesApi::class) @OptIn(DelicateCoroutinesApi::class)
suspend fun main() { suspend fun main() {
initializeLogger(File(userDataDir, "logging")) initializeLogger(userDataDir.resolve(userDataDir, "logging"))
if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) {
System.setProperty("kotlinx.coroutines.debug", "on") System.setProperty("kotlinx.coroutines.debug", "on")

View File

@@ -47,8 +47,11 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File import java.nio.file.Path
import javax.inject.Inject import javax.inject.Inject
import kotlin.io.path.absolutePathString
import kotlin.io.path.notExists
import kotlin.io.path.outputStream
class SettingsBackupViewModel @Inject constructor( class SettingsBackupViewModel @Inject constructor(
private val backupHandler: BackupInteractionHandler private val backupHandler: BackupInteractionHandler
@@ -59,7 +62,7 @@ class SettingsBackupViewModel @Inject constructor(
val restoringProgress = _restoringProgress.asStateFlow() val restoringProgress = _restoringProgress.asStateFlow()
private val _restoreStatus = MutableStateFlow<Status>(Status.Nothing) private val _restoreStatus = MutableStateFlow<Status>(Status.Nothing)
internal val restoreStatus = _restoreStatus.asStateFlow() internal val restoreStatus = _restoreStatus.asStateFlow()
private val _missingSourceFlow = MutableSharedFlow<Pair<File, List<String>>>() private val _missingSourceFlow = MutableSharedFlow<Pair<Path, List<String>>>()
val missingSourceFlow = _missingSourceFlow.asSharedFlow() val missingSourceFlow = _missingSourceFlow.asSharedFlow()
private val _creating = MutableStateFlow(false) private val _creating = MutableStateFlow(false)
@@ -68,13 +71,13 @@ class SettingsBackupViewModel @Inject constructor(
val creatingProgress = _creatingProgress.asStateFlow() val creatingProgress = _creatingProgress.asStateFlow()
private val _creatingStatus = MutableStateFlow<Status>(Status.Nothing) private val _creatingStatus = MutableStateFlow<Status>(Status.Nothing)
internal val creatingStatus = _creatingStatus.asStateFlow() internal val creatingStatus = _creatingStatus.asStateFlow()
private val _createFlow = MutableSharedFlow<Pair<String, (File) -> Unit>>() private val _createFlow = MutableSharedFlow<Pair<String, (Path) -> Unit>>()
val createFlow = _createFlow.asSharedFlow() val createFlow = _createFlow.asSharedFlow()
fun restoreFile(file: File?) { fun restoreFile(file: Path?) {
scope.launch { scope.launch {
if (file == null || !file.exists()) { if (file == null || file.notExists()) {
info { "Invalid file ${file?.absolutePath}" } info { "Invalid file ${file?.absolutePathString()}" }
_restoreStatus.value = Status.Error _restoreStatus.value = Status.Error
_restoring.value = false _restoring.value = false
} else { } else {
@@ -94,7 +97,7 @@ class SettingsBackupViewModel @Inject constructor(
} }
} }
fun restoreBackup(file: File) { fun restoreBackup(file: Path) {
scope.launch { scope.launch {
_restoreStatus.value = Status.Nothing _restoreStatus.value = Status.Nothing
_restoringProgress.value = null _restoringProgress.value = null
@@ -189,7 +192,7 @@ fun SettingsBackupScreen(menuController: MenuController) {
launch { launch {
vm.createFlow.collect { (filename, function) -> vm.createFlow.collect { (filename, function) ->
fileSaver(filename, "proto.gz") { fileSaver(filename, "proto.gz") {
function(it.selectedFile) function(it.selectedFile.toPath())
} }
} }
} }
@@ -207,7 +210,7 @@ fun SettingsBackupScreen(menuController: MenuController) {
restoreStatus restoreStatus
) { ) {
filePicker("gz") { filePicker("gz") {
vm.restoreFile(it.selectedFile) vm.restoreFile(it.selectedFile.toPath())
} }
} }
PreferenceFile( PreferenceFile(

View File

@@ -13,11 +13,12 @@ import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.get import io.ktor.client.request.get
import io.ktor.utils.io.ByteReadChannel import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.jvm.javaio.copyTo import io.ktor.utils.io.jvm.javaio.copyTo
import org.jetbrains.skija.Image import org.jetbrains.skia.Image
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.File import java.nio.file.Path
import kotlin.io.path.readBytes
fun imageFromFile(file: File): ImageBitmap { fun imageFromFile(file: Path): ImageBitmap {
return Image.makeFromEncoded(file.readBytes()).asImageBitmap() return Image.makeFromEncoded(file.readBytes()).asImageBitmap()
} }

View File

@@ -12,9 +12,12 @@ import kotlinx.coroutines.DelicateCoroutinesApi
import mu.KotlinLogging import mu.KotlinLogging
import net.harawata.appdirs.AppDirs import net.harawata.appdirs.AppDirs
import net.harawata.appdirs.AppDirsFactory import net.harawata.appdirs.AppDirsFactory
import java.io.File import java.nio.file.Path
import javax.swing.JFileChooser import javax.swing.JFileChooser
import javax.swing.filechooser.FileNameExtensionFilter import javax.swing.filechooser.FileNameExtensionFilter
import kotlin.io.path.Path
import kotlin.io.path.createDirectories
import kotlin.io.path.exists
private val logger = KotlinLogging.logger {} private val logger = KotlinLogging.logger {}
@@ -22,10 +25,10 @@ val appDirs: AppDirs by lazy {
AppDirsFactory.getInstance() AppDirsFactory.getInstance()
} }
val userDataDir: File by lazy { val userDataDir: Path by lazy {
File(appDirs.getUserDataDir(BuildConfig.NAME, null, null)).also { Path(appDirs.getUserDataDir(BuildConfig.NAME, null, null)).also {
if (!it.exists()) { if (!it.exists()) {
logger.info("Attempted to create app data dir, result: {}", it.mkdirs()) logger.info("Attempted to create app data dir, result: {}", it.createDirectories())
} }
} }
} }
@@ -82,7 +85,7 @@ private fun fileChooser(
fileFilter = FileNameExtensionFilter("${extensions.joinToString()} files", *extensions) fileFilter = FileNameExtensionFilter("${extensions.joinToString()} files", *extensions)
} }
if (saving) { if (saving) {
selectedFile = File(defaultFileName) selectedFile = Path(defaultFileName).toFile()
} }
} }
.apply(builder) .apply(builder)