-
Notifications
You must be signed in to change notification settings - Fork 32
/
Repository.kt
134 lines (112 loc) · 4.89 KB
/
Repository.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package com.cognifide.gradle.aem.common.instance.service.repository
import com.cognifide.gradle.aem.common.instance.InstanceService
import com.cognifide.gradle.aem.common.instance.InstanceSync
import com.cognifide.gradle.common.http.RequestException
import com.cognifide.gradle.common.http.ResponseException
import java.io.File
class Repository(sync: InstanceSync) : InstanceService(sync) {
/**
* Take care about property value types saved in repository.
*/
val typeHints = aem.obj.boolean {
convention(true)
aem.prop.boolean("instance.repository.typeHints")?.let { set(it) }
}
/**
* Controls level of logging. By default repository related operations are only logged at debug level.
* This switch could increase logging level to info level.
*/
val verboseLogging = aem.obj.boolean {
convention(false)
aem.prop.boolean("instance.repository.verboseLogging")?.let { set(it) }
}
/**
* Controls throwing exceptions in case of response statuses indicating repository errors.
* Switching it to false, allows custom error handling in task scripting.
*/
val responseChecks = aem.obj.boolean {
convention(true)
aem.prop.boolean("instance.repository.responseChecks")?.let { set(it) }
}
/**
* When trying to upload file under '/content/dam', repository will use for upload dedicated AEM service
* instead of using Sling service.
*/
val damUploads = aem.obj.boolean {
convention(true)
aem.prop.boolean("instance.repository.damUploads")?.let { set(it) }
}
/**
* Get node at given path.
*/
fun node(path: String) = Node(this, path)
/**
* Get node at given path and perform action in its scope (and optionally return result).
*/
fun <T> node(path: String, action: Node.() -> T): T = node(path).run(action)
/**
* Shorthand method for creating or updating node at given path.
*/
fun save(path: String, properties: Map<String, Any?>): RepositoryResult {
val (dir, name) = splitPath(path)
return when {
name.contains(".") -> node(dir).import(properties, name, replace = true, replaceProperties = true)
else -> node(path).save(properties)
}
}
/**
* Shorthand method for importing content from JSON file at given path.
*/
fun import(path: String, jsonFile: File): RepositoryResult {
val (dir, name) = splitPath(path)
return node(dir).import(jsonFile, name, replace = true, replaceProperties = true)
}
/**
* Shorthand method for importing content using specified JSON.
*/
fun import(path: String, json: String): RepositoryResult {
val (dir, name) = splitPath(path)
return node(dir).import(json, name, replace = true, replaceProperties = true)
}
/**
* Execute repository query to find desired nodes.
*/
fun query(criteria: QueryCriteria.() -> Unit): Query = query(QueryCriteria().apply(criteria))
/**
* Execute repository query to find desired nodes.
*/
fun query(criteria: QueryCriteria): Query = try {
val path = "$QUERY_BUILDER_PATH?${criteria.queryString}"
log("Querying repository using URL '${instance.httpUrl.get()}$path'")
val result = http.get(path) { asObjectFromJson<QueryResult>(it) }
Query(this, criteria, result)
} catch (e: RequestException) {
throw RepositoryException("Cannot perform $criteria on $instance. Cause: ${e.message}", e)
} catch (e: ResponseException) {
throw RepositoryException("Malformed response after querying $criteria on $instance. Cause: ${e.message}", e)
}
fun replicationAgent(location: String, name: String) = ReplicationAgent(node("/etc/replication/agents.$location/$name"))
fun replicationAgents(location: String): Sequence<ReplicationAgent> = node("/etc/replication/agents.$location").children()
.filter { it.type == "cq:Page" }
.map { ReplicationAgent(it) }
fun replicationAgents(): Sequence<ReplicationAgent> {
return replicationAgents(ReplicationAgent.LOCATION_AUTHOR) + replicationAgents(ReplicationAgent.LOCATION_PUBLISH)
}
val replicationAgents: List<ReplicationAgent> get() = replicationAgents().toList()
private fun splitPath(path: String): Pair<String, String> {
return path.substringBeforeLast("/") to path.substringAfterLast("/")
}
internal fun log(message: String, e: Throwable? = null) = when {
verboseLogging.get() -> logger.info(message, e)
else -> logger.debug(message, e)
}
internal val http by lazy {
RepositoryHttpClient(aem, instance).apply {
responseChecks.set([email protected])
}
}
companion object {
const val QUERY_BUILDER_PATH = "/bin/querybuilder.json"
const val SLING_INSTALLER_PAUSE = "/system/sling/installer/jcr/pauseInstallation"
}
}