diff --git a/vripper-core/src/main/kotlin/me/mnlr/vripper/listeners/AppLock.kt b/vripper-core/src/main/kotlin/me/mnlr/vripper/listeners/AppLock.kt new file mode 100644 index 00000000..020c3e64 --- /dev/null +++ b/vripper-core/src/main/kotlin/me/mnlr/vripper/listeners/AppLock.kt @@ -0,0 +1,44 @@ +package me.mnlr.vripper.listeners + +import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent +import org.springframework.context.ApplicationListener +import java.io.RandomAccessFile +import java.nio.file.Files +import kotlin.io.path.Path +import kotlin.io.path.pathString +import kotlin.system.exitProcess + +class AppLock : ApplicationListener { + override fun onApplicationEvent(event: ApplicationEnvironmentPreparedEvent) { + val baseDir = event.environment.getProperty("base.dir") + val appDirName = event.environment.getProperty("base.dir.name") + if (baseDir == null || appDirName == null) { + if (baseDir == null) { + System.err.println("Property base.dir is undefined") + } + if (appDirName == null) { + System.err.println("Property base.dir.name is undefined") + } + System.err.println("Misconfiguration detected, quitting...") + exitProcess(-1) + } + val lock = Path(baseDir).resolve(appDirName).resolve("lock") + try { + val randomFile = RandomAccessFile(lock.pathString, "rw") + val channel = randomFile.channel + val fileLock = channel.tryLock() + if (fileLock == null) { + System.err.println("Another instance is already running in ${lock.parent.pathString}") + exitProcess(-1) + } else { + Runtime.getRuntime().addShutdownHook(Thread { + fileLock.release() + channel.close() + Files.deleteIfExists(lock) + }) + } + } catch (e: Exception) { + println(e.toString()) + } + } +} \ No newline at end of file diff --git a/vripper-gui/src/main/kotlin/me/mnlr/vripper/VripperGuiApplication.kt b/vripper-gui/src/main/kotlin/me/mnlr/vripper/VripperGuiApplication.kt index da705a5a..b109966d 100644 --- a/vripper-gui/src/main/kotlin/me/mnlr/vripper/VripperGuiApplication.kt +++ b/vripper-gui/src/main/kotlin/me/mnlr/vripper/VripperGuiApplication.kt @@ -6,7 +6,7 @@ import javafx.stage.Stage import javafx.stage.WindowEvent import me.mnlr.vripper.event.ApplicationInitialized import me.mnlr.vripper.gui.Styles -import me.mnlr.vripper.listeners.AppListener +import me.mnlr.vripper.listeners.AppLock import me.mnlr.vripper.view.LoadingView import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.builder.SpringApplicationBuilder @@ -44,7 +44,7 @@ class VripperGuiApplication : App( } stage.addEventFilter(WindowEvent.WINDOW_SHOWN) { val contextInitThread = Thread { - context = SpringApplicationBuilder(this.javaClass).listeners(AppListener()) + context = SpringApplicationBuilder(this.javaClass).listeners(AppLock()) .run() //We start the application context and let Spring Boot to initialize itself context.autowireCapableBeanFactory.autowireBean(this) //We ask the context to inject all needed dependencies into the current instence (if needed) diff --git a/vripper-web/src/main/kotlin/me/mnlr/vripper/VripperWebApplication.kt b/vripper-web/src/main/kotlin/me/mnlr/vripper/VripperWebApplication.kt index 25c1dfbf..4569f551 100644 --- a/vripper-web/src/main/kotlin/me/mnlr/vripper/VripperWebApplication.kt +++ b/vripper-web/src/main/kotlin/me/mnlr/vripper/VripperWebApplication.kt @@ -1,6 +1,6 @@ package me.mnlr.vripper -import me.mnlr.vripper.listeners.AppListener +import me.mnlr.vripper.listeners.AppLock import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.builder.SpringApplicationBuilder @@ -8,5 +8,5 @@ import org.springframework.boot.builder.SpringApplicationBuilder class VripperWebApplication fun main(args: Array) { - SpringApplicationBuilder(VripperWebApplication::class.java).listeners(AppListener()).run(*args) + SpringApplicationBuilder(VripperWebApplication::class.java).listeners(AppLock()).run(*args) }