package ru.mipt.spc import io.ktor.server.application.Application import io.ktor.server.application.log import kotlinx.css.CssBuilder import kotlinx.html.CommonAttributeGroupFacade import kotlinx.html.style import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.fetch import space.kscience.snark.SnarkPlugin import space.kscience.snark.site import java.net.URI import java.nio.file.FileSystems import java.nio.file.Files import java.nio.file.Path import java.time.LocalDateTime import kotlin.io.path.* fun CommonAttributeGroupFacade.css(block: CssBuilder.() -> Unit) { style = CssBuilder().block().toString() } private fun Application.resolveData(uri: URI, targetPath: Path): Path { if (Files.isDirectory(targetPath)) { log.info("Using existing data directory at $targetPath.") } else { log.info("Copying data from $uri into $targetPath.") targetPath.createDirectories() //Copy everything into a temporary directory FileSystems.newFileSystem(uri, emptyMap<String, Any>()).use { fs -> val rootPath: Path = fs.provider().getPath(uri) Files.walk(rootPath).forEach { source: Path -> if (source.isRegularFile()) { val relative = source.relativeTo(rootPath).toString() val destination: Path = targetPath.resolve(relative) destination.parent.createDirectories() Files.copy(source, destination) } } } } return targetPath } const val DEPLOY_DATE_FILE = "deployDate" const val BUILD_DATE_FILE = "/buildDate" @Suppress("unused") fun Application.spcModule() { val context = Context("spc-site") { plugin(SnarkPlugin) } val snark = context.fetch(SnarkPlugin) val dataPath = Path.of("data") // Clear data directory if it is outdated val deployDate = dataPath.resolve(DEPLOY_DATE_FILE).takeIf { it.exists() } ?.readText()?.let { LocalDateTime.parse(it) } val buildDate = javaClass.getResource(BUILD_DATE_FILE)?.readText()?.let { LocalDateTime.parse(it) } val inProduction: Boolean = environment.config.propertyOrNull("ktor.environment.production") != null if(inProduction){ log.info("Production mode activated") log.info("Build date: $buildDate") log.info("Deploy date: $deployDate") } if (deployDate != null && buildDate != null && buildDate.isAfter(deployDate)) { log.info("Outdated data. Resetting data directory.") Files.walk(dataPath) .sorted(Comparator.reverseOrder()) .forEach { it.deleteIfExists() } //Writing deploy date file dataPath.createDirectories() dataPath.resolve(DEPLOY_DATE_FILE).writeText(LocalDateTime.now().toString()) } else if (inProduction && deployDate == null && buildDate != null) { val date = LocalDateTime.now().toString() log.info("Deploy date: $date") //Writing deploy date in production mode if it does not exist dataPath.createDirectories() dataPath.resolve(DEPLOY_DATE_FILE).writeText(date) } snark.site { val homeDataPath = resolveData( this@spcModule.javaClass.getResource("/home")!!.toURI(), dataPath / "home" ) spcHome(rootPath = homeDataPath) val mastersDataPath = resolveData( this@spcModule.javaClass.getResource("/magprog")!!.toURI(), dataPath / "magprog" ) spcMaster(dataPath = mastersDataPath) } } fun main(args: Array<String>) = io.ktor.server.netty.EngineMain.main(args)