Store on local jar files to have valid timestamp
This commit is contained in:
@@ -19,8 +19,10 @@ package org.jetbrains.kotlin.idea.caches
|
|||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.openapi.components.ServiceManager
|
import com.intellij.openapi.components.ServiceManager
|
||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
|
import com.intellij.openapi.vfs.StandardFileSystems
|
||||||
import com.intellij.openapi.vfs.VfsUtilCore
|
import com.intellij.openapi.vfs.VfsUtilCore
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
import com.intellij.util.io.URLUtil
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
|
|
||||||
public object JarUserDataManager {
|
public object JarUserDataManager {
|
||||||
@@ -30,7 +32,7 @@ public object JarUserDataManager {
|
|||||||
NO_FILE
|
NO_FILE
|
||||||
}
|
}
|
||||||
|
|
||||||
val version = 1
|
val version = 2
|
||||||
|
|
||||||
val fileAttributeService: FileAttributeService? = ServiceManager.getService(javaClass<FileAttributeService>())
|
val fileAttributeService: FileAttributeService? = ServiceManager.getService(javaClass<FileAttributeService>())
|
||||||
|
|
||||||
@@ -39,44 +41,39 @@ public object JarUserDataManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun hasFileWithProperty(counter: JarBooleanPropertyCounter, file: VirtualFile): Boolean? {
|
public fun hasFileWithProperty(counter: JarBooleanPropertyCounter, file: VirtualFile): Boolean? {
|
||||||
val jarFile = findJarRoot(file) ?: return null
|
val localJarFile = JarFileSystemUtil.findLocalJarFile(file) ?: return null
|
||||||
|
|
||||||
val stored = jarFile.getUserData(counter.key)
|
val stored = localJarFile.getUserData(counter.key)
|
||||||
if (stored != null && jarFile.timeStamp == stored.timestamp) {
|
if (stored != null) {
|
||||||
return stored.hasFileWithProperty
|
if (localJarFile.timeStamp == stored.timestamp) {
|
||||||
|
return stored.hasFileWithProperty
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stored == null && fileAttributeService != null) {
|
if (stored == null && fileAttributeService != null) {
|
||||||
val savedData = fileAttributeService.readAttribute(counter.key.toString(), jarFile, javaClass<State>())
|
val savedData = fileAttributeService.readAttribute(counter.key.toString(), localJarFile, javaClass<State>())
|
||||||
if (savedData != null && savedData.value != null) {
|
if (savedData != null && savedData.value != null) {
|
||||||
val hasFileWithProperty = savedData.value == State.HAS_FILE
|
val hasFileWithProperty = savedData.value == State.HAS_FILE
|
||||||
|
|
||||||
jarFile.putUserData(counter.key, PropertyData(hasFileWithProperty, savedData.timeStamp))
|
storeUserData(counter, localJarFile, hasFileWithProperty, savedData.timeStamp)
|
||||||
|
|
||||||
if (jarFile.timeStamp == savedData.timeStamp) {
|
if (localJarFile.timeStamp == savedData.timeStamp) {
|
||||||
return hasFileWithProperty
|
return hasFileWithProperty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleJarProcessing(counter, jarFile)
|
val jarFileRoot = JarFileSystemUtil.findJarFileRoot(file) ?: return null
|
||||||
|
scheduleJarProcessing(counter, jarFileRoot, localJarFile)
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findJarRoot(file: VirtualFile): VirtualFile? {
|
private fun scheduleJarProcessing(counter: JarBooleanPropertyCounter, jarFile: VirtualFile, localJarFile: VirtualFile) {
|
||||||
if (!file.getUrl().startsWith("jar://")) return null
|
val userData = localJarFile.getUserData(counter.key)
|
||||||
|
if (userData != null && localJarFile.timeStamp == userData.timestamp) return
|
||||||
|
|
||||||
var jarFile = file
|
storeUserData(counter, localJarFile, null)
|
||||||
while (jarFile.getParent() != null) jarFile = jarFile.getParent()
|
|
||||||
|
|
||||||
return jarFile
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun scheduleJarProcessing(counter: JarBooleanPropertyCounter, jarFile: VirtualFile) {
|
|
||||||
if (jarFile.getUserData(counter.key) != null) return
|
|
||||||
|
|
||||||
jarFile.putUserData(counter.key, PropertyData(null, jarFile.timeStamp))
|
|
||||||
|
|
||||||
ApplicationManager.getApplication().executeOnPooledThread {
|
ApplicationManager.getApplication().executeOnPooledThread {
|
||||||
runReadAction {
|
runReadAction {
|
||||||
@@ -86,15 +83,45 @@ public object JarUserDataManager {
|
|||||||
|
|
||||||
val state = if (hasFileWithProperty) State.HAS_FILE else State.NO_FILE
|
val state = if (hasFileWithProperty) State.HAS_FILE else State.NO_FILE
|
||||||
|
|
||||||
val savedData = fileAttributeService?.writeAttribute(counter.key.toString(), jarFile, state)
|
val savedData = fileAttributeService?.writeAttribute(counter.key.toString(), localJarFile, state)
|
||||||
|
|
||||||
jarFile.putUserData(
|
storeUserData(counter, localJarFile, hasFileWithProperty, (savedData?.timeStamp ?: localJarFile.timeStamp))
|
||||||
counter.key,
|
|
||||||
PropertyData(hasFileWithProperty, (savedData?.timeStamp ?: jarFile.timeStamp)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun storeUserData(counter: JarBooleanPropertyCounter, localJarFile: VirtualFile,
|
||||||
|
hasFileWithProperty: Boolean?, timestamp: Long? = null) {
|
||||||
|
assert(localJarFile.isInLocalFileSystem)
|
||||||
|
assert((timestamp == null) == (hasFileWithProperty == null), "Using empty timestamp is only allowed for storing not counted value")
|
||||||
|
|
||||||
|
localJarFile.putUserData(counter.key,
|
||||||
|
PropertyData(hasFileWithProperty, timestamp ?: localJarFile.timeStamp))
|
||||||
|
}
|
||||||
|
|
||||||
|
object JarFileSystemUtil {
|
||||||
|
public fun findJarFileRoot(inJarFile: VirtualFile): VirtualFile? {
|
||||||
|
if (!inJarFile.getUrl().startsWith("jar://")) return null
|
||||||
|
|
||||||
|
var jarFile = inJarFile
|
||||||
|
while (jarFile.getParent() != null) jarFile = jarFile.getParent()
|
||||||
|
|
||||||
|
return jarFile
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun findLocalJarFile(inJarFile: VirtualFile): VirtualFile? {
|
||||||
|
if (!inJarFile.getUrl().startsWith("jar://")) return null
|
||||||
|
|
||||||
|
val path = inJarFile.getPath()
|
||||||
|
|
||||||
|
val jarSeparatorIndex = path.indexOf(URLUtil.JAR_SEPARATOR)
|
||||||
|
assert(jarSeparatorIndex >= 0) { "Path passed to JarFileSystem must have jar separator '!/': $path" }
|
||||||
|
val localPath = path.substring(0, jarSeparatorIndex)
|
||||||
|
|
||||||
|
return StandardFileSystems.local().findFileByPath(localPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data class PropertyData(val hasFileWithProperty: Boolean?, val timestamp: Long)
|
data class PropertyData(val hasFileWithProperty: Boolean?, val timestamp: Long)
|
||||||
|
|
||||||
abstract class JarBooleanPropertyCounter(keyName: String) {
|
abstract class JarBooleanPropertyCounter(keyName: String) {
|
||||||
|
|||||||
Reference in New Issue
Block a user