1
1
package org.javacs.kt.classpath
2
2
3
- import kotlinx.serialization.Serializable
4
- import org.javacs.kt.storage.SetOfPathsAsStringSerializer
5
- import org.javacs.kt.storage.Storage
3
+ import org.jetbrains.exposed.dao.IntEntity
4
+ import org.jetbrains.exposed.dao.IntEntityClass
5
+ import org.jetbrains.exposed.dao.id.EntityID
6
+ import org.jetbrains.exposed.dao.id.IntIdTable
7
+ import org.jetbrains.exposed.sql.*
8
+ import org.jetbrains.exposed.sql.transactions.transaction
6
9
import java.nio.file.Path
10
+ import java.nio.file.Paths
11
+
12
+ private const val MAX_PATH_LENGTH = 255
13
+
14
+ private object ClassPathMetadataCache : IntIdTable() {
15
+ val includesSources = bool(" includessources" )
16
+ val buildFileVersion = long(" buidlfileversion" ).nullable()
17
+ }
18
+
19
+ private object ClassPathCacheEntry : IntIdTable() {
20
+ val compiledJar = varchar(" compiledjar" , length = MAX_PATH_LENGTH )
21
+ val sourceJar = varchar(" sourcejar" , length = MAX_PATH_LENGTH ).nullable()
22
+ }
23
+
24
+ private object BuildScriptClassPathCacheEntry : IntIdTable() {
25
+ val jar = varchar(" jar" , length = MAX_PATH_LENGTH )
26
+ }
27
+
28
+ class ClassPathMetadataCacheEntity (id : EntityID <Int >) : IntEntity(id) {
29
+ companion object : IntEntityClass <ClassPathMetadataCacheEntity >(ClassPathMetadataCache )
30
+
31
+ var includesSources by ClassPathMetadataCache .includesSources
32
+ var buildFileVersion by ClassPathMetadataCache .buildFileVersion
33
+ }
34
+
35
+ class ClassPathCacheEntryEntity (id : EntityID <Int >) : IntEntity(id) {
36
+ companion object : IntEntityClass <ClassPathCacheEntryEntity >(ClassPathCacheEntry )
37
+
38
+ var compiledJar by ClassPathCacheEntry .compiledJar
39
+ var sourceJar by ClassPathCacheEntry .sourceJar
40
+ }
41
+
42
+ class BuildScriptClassPathCacheEntryEntity (id : EntityID <Int >) : IntEntity(id) {
43
+ companion object : IntEntityClass <BuildScriptClassPathCacheEntryEntity >(BuildScriptClassPathCacheEntry )
44
+
45
+ var jar by BuildScriptClassPathCacheEntry .jar
46
+ }
7
47
8
48
/* * A classpath resolver that caches another resolver */
9
- internal class CachedClassPathResolver (private val wrapped : ClassPathResolver , private val storage : Storage ? ) : ClassPathResolver {
49
+ internal class CachedClassPathResolver (private val wrapped : ClassPathResolver , private val db : Database ) : ClassPathResolver {
10
50
override val resolverType: String get() = " Cached + ${wrapped.resolverType} "
11
51
12
- private var cachedClassPath: ClasspathCache ? = storage?.getObject(" cachedClasspath" )
13
- private var cachedBuildScriptClassPath: Set <Path >? = storage?.getObject(" cachedBuildScriptClassPath" , SetOfPathsAsStringSerializer )
52
+ private var cachedClassPathEntries: Set <ClassPathEntry >
53
+ get() = transaction(db) { ClassPathCacheEntryEntity .all() }.map {
54
+ ClassPathEntry (
55
+ compiledJar = Paths .get(it.compiledJar),
56
+ sourceJar = if (it.sourceJar != null ) Paths .get(it.sourceJar) else null
57
+ )
58
+ }.toSet()
59
+ set(newEntries) = transaction(db) {
60
+ ClassPathCacheEntry .deleteAll()
61
+ newEntries.map {
62
+ ClassPathCacheEntryEntity .new {
63
+ compiledJar = it.compiledJar.toString()
64
+ sourceJar = it.sourceJar.toString()
65
+ }
66
+ }
67
+ }
68
+
69
+ private var cachedBuildScriptClassPathEntries: Set <Path >
70
+ get() = transaction(db) { BuildScriptClassPathCacheEntryEntity .all() }.map { Paths .get(it.jar) }.toSet()
71
+ set(newEntries) = transaction(db) {
72
+ BuildScriptClassPathCacheEntry .deleteAll()
73
+ newEntries.map { BuildScriptClassPathCacheEntryEntity .new { jar = it.toString() } }
74
+ }
75
+
76
+ private var cachedClassPathMetadata
77
+ get() = transaction(db) { ClassPathMetadataCacheEntity .all().map {
78
+ ClasspathMetadata (
79
+ includesSources = it.includesSources,
80
+ buildFileVersion = it.buildFileVersion
81
+ )
82
+ }.firstOrNull() }
83
+ set(newClassPathMetadata) = transaction(db) {
84
+ ClassPathMetadataCache .deleteAll()
85
+ val newClassPathMetadataRow = newClassPathMetadata ? : ClasspathMetadata ()
86
+ ClassPathMetadataCacheEntity .new {
87
+ includesSources = newClassPathMetadataRow.includesSources
88
+ buildFileVersion = newClassPathMetadataRow.buildFileVersion
89
+ }
90
+ }
91
+
92
+ init {
93
+ transaction(db) {
94
+ SchemaUtils .createMissingTablesAndColumns(ClassPathMetadataCache , ClassPathCacheEntry , BuildScriptClassPathCacheEntry )
95
+ }
96
+ }
14
97
15
98
override val classpath: Set <ClassPathEntry > get() {
16
- cachedClassPath? .let { if (! dependenciesChanged()) return it.classpathEntries }
99
+ cachedClassPathEntries .let { if (! dependenciesChanged()) return it }
17
100
18
101
val newClasspath = wrapped.classpath
19
- updateClasspathCache(ClasspathCache ( newClasspath, false ) )
102
+ updateClasspathCache(newClasspath, false )
20
103
21
104
return newClasspath
22
105
}
23
106
24
107
override val buildScriptClasspath: Set <Path > get() {
25
- cachedBuildScriptClassPath?. let { if (! dependenciesChanged()) return it }
108
+ if (! dependenciesChanged()) return cachedBuildScriptClassPathEntries
26
109
27
110
val newBuildScriptClasspath = wrapped.buildScriptClasspath
28
111
@@ -31,35 +114,39 @@ internal class CachedClassPathResolver(private val wrapped: ClassPathResolver, p
31
114
}
32
115
33
116
override val classpathWithSources: Set <ClassPathEntry > get() {
34
- cachedClassPath ?.let { if (! dependenciesChanged() && it.includesSources) return it.classpathEntries }
117
+ cachedClassPathMetadata ?.let { if (! dependenciesChanged() && it.includesSources) return cachedClassPathEntries }
35
118
36
119
val newClasspath = wrapped.classpathWithSources
37
- updateClasspathCache(ClasspathCache ( newClasspath, true ) )
120
+ updateClasspathCache(newClasspath, true )
38
121
39
122
return newClasspath
40
123
}
41
124
42
125
override val currentBuildFileVersion: Long get() = wrapped.currentBuildFileVersion
43
126
44
- private fun updateClasspathCache (newClasspathCache : ClasspathCache ) {
45
- storage?.setObject(" cachedClasspath" , newClasspathCache)
46
- storage?.setObject(" cachedBuildFileVersion" , currentBuildFileVersion)
47
- cachedClassPath = newClasspathCache
127
+ private fun updateClasspathCache (newClasspathEntries : Set <ClassPathEntry >, includesSources : Boolean ) {
128
+ transaction(db) {
129
+ cachedClassPathEntries = newClasspathEntries
130
+ cachedClassPathMetadata = cachedClassPathMetadata?.copy(
131
+ includesSources = includesSources,
132
+ buildFileVersion = currentBuildFileVersion
133
+ ) ? : ClasspathMetadata ()
134
+ }
48
135
}
49
136
50
137
private fun updateBuildScriptClasspathCache (newClasspath : Set <Path >) {
51
- storage?.setObject(" cachedBuildScriptClassPath" , newClasspath, SetOfPathsAsStringSerializer )
52
- storage?.setObject(" cachedBuildFileVersion" , currentBuildFileVersion)
53
- cachedBuildScriptClassPath = newClasspath
138
+ transaction(db) {
139
+ cachedBuildScriptClassPathEntries = newClasspath
140
+ cachedClassPathMetadata = cachedClassPathMetadata?.copy(buildFileVersion = currentBuildFileVersion) ? : ClasspathMetadata ()
141
+ }
54
142
}
55
143
56
144
private fun dependenciesChanged (): Boolean {
57
- return storage?.getObject< Long >( " cachedBuildFileVersion " ) ? : 0 < wrapped.currentBuildFileVersion
145
+ return (cachedClassPathMetadata?.buildFileVersion ? : 0 ) < wrapped.currentBuildFileVersion
58
146
}
59
147
}
60
148
61
- @Serializable
62
- private data class ClasspathCache (
63
- val classpathEntries : Set <ClassPathEntry >,
64
- val includesSources : Boolean
149
+ private data class ClasspathMetadata (
150
+ val includesSources : Boolean = false ,
151
+ val buildFileVersion : Long? = null
65
152
)
0 commit comments