All Downloads are FREE. Search and download functionalities are using the official Maven repository.

name.remal.gradle_plugins.dsl.cache.BaseCache.kt Maven / Gradle / Ivy

There is a newer version: 1.9.2
Show newest version
package name.remal.gradle_plugins.dsl.cache

import name.remal.forLockedFileChannel
import name.remal.forceDeleteRecursively
import name.remal.lockAndReadBytes
import name.remal.lockAndWriteBytes
import org.gradle.wrapper.GradleUserHomeLookup.gradleUserHome
import java.io.File
import java.nio.ByteBuffer

abstract class BaseCache(protected val cacheId: String, protected val version: Int) {

    companion object {
        protected val baseCacheDir: File = File(gradleUserHome(), "caches/remal-gradle-plugins").absoluteFile
        private val CACHE_ID_REGEX = Regex("[\\w./-]+")
    }

    protected abstract val serializer: (value: WriteValueType) -> ByteArray?
    protected abstract val deserializer: (bytes: ByteArray) -> ReadValueType?

    init {
        if (!cacheId.matches(CACHE_ID_REGEX)) {
            throw IllegalArgumentException("Cache ID '$cacheId' doesn't match to '$CACHE_ID_REGEX' regex")
        }
        if (version <= 0) {
            throw IllegalArgumentException("version <= 0: $version")
        }
    }

    private val cacheFile = File(baseCacheDir, buildString {
        if (cacheId.contains('/')) {
            append(cacheId.substringBeforeLast('/')).append('/')
        }
        val fileName = cacheId.substringAfterLast('/')
        val extPos = fileName.lastIndexOf('.')
        if (0 <= extPos) {
            append(fileName.substring(0, extPos))
            append(".").append(version)
            append(fileName.substring(extPos))
        } else {
            append(fileName)
            append(".").append(version)
        }
    })

    fun write(value: WriteValueType?) {
        val bytes = value?.let(serializer)
        if (bytes == null) {
            cacheFile.forceDeleteRecursively()
        } else {
            cacheFile.lockAndWriteBytes(bytes)
        }
    }

    fun read(): ReadValueType? {
        if (cacheFile.exists()) {
            val bytes = cacheFile.lockAndReadBytes()
            val value = deserializer(bytes)
            return value
        } else {
            return null
        }
    }

    fun compute(func: (currentValue: ReadValueType?) -> WriteValueType?) {
        synchronized(this) {
            cacheFile.forLockedFileChannel { channel ->
                val currentValue = read()
                val value = func(currentValue)
                val bytes = value?.let(serializer)
                if (bytes == null) {
                    cacheFile.forceDeleteRecursively()
                } else {
                    channel.write(ByteBuffer.wrap(bytes))
                }
                Unit
            }
        }
    }

    override fun toString() = "${javaClass.simpleName}[$cacheId/$version]"

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy