-
Notifications
You must be signed in to change notification settings - Fork 53
/
Copy pathbuild.gradle
407 lines (359 loc) · 16 KB
/
build.gradle
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
import org.apereo.portal.start.gradle.plugins.GradleImportExportPlugin
import org.apereo.portal.start.gradle.plugins.GradlePlutoPlugin
dependencies {
runtime "org.jasig.portal:uPortal-webapp:${uPortalVersion}@war"
compile configurations.jdbc
}
apply plugin: GradleImportExportPlugin
apply plugin: GradlePlutoPlugin
apply plugin: 'com.github.node-gradle.node'
node {
version = nodejsVersion
download = true
}
war {
archiveName 'uPortal.war'
/*
* For uPortal 5 (and beyond), the Community Best Practice for WAR files published to Maven
* Central is that they should *not* contain JDBC driver jars; all such WAR files are
* implemented locally by "overlaying" them, and it is the responsibility of they overlaying
* project (here uPortal-start) to provide them with the appropriate drivers. When the
* published artifacts already contain drivers, the danger of conflicting versions is very
* high.
*
* Nevertheless, earlier versions of uPortal and Apereo portlets *do* contain JDBC drivers,
* specifically HSQLDB. The following exclusion prevents the copy of this driver contained
* within the published WAR file from being deployed. Please remove this line when the
* published artifact reliably omits the HSQLDB driver.
*
* See https://github.com/Jasig/uPortal-start/pull/120
*/
exclude 'WEB-INF/lib/hsqldb-*.jar'
}
/*
* Skinning Support
*/
import java.util.regex.Pattern
File skinsDir = rootProject.file("${projectDir}/src/main/webapp/media/skins/respondr")
task skinGenerate() {
group 'Skin'
description 'Genarate a new uPortal skin for Respondr; pass -DskinName={name} (required) to specify a name'
doLast {
String skinName = System.getProperty('skinName');
if (skinName == null || skinName.isEmpty()) {
throw new GradleException('You must specify a skinName JVM argment to invoke the skinGenerate task')
}
// We have a name; but is it valid?
if (!Pattern.matches(/[a-zA-Z0-9]{3,20}/, skinName)) {
throw new GradleException('A valid skinName contains between 3 and 20 alphanumeric characters')
}
File skinFile = rootProject.file("${projectDir}/src/main/webapp/media/skins/respondr/${skinName}.less")
File skinDir = rootProject.file("${projectDir}/src/main/webapp/media/skins/respondr/${skinName}")
if (skinFile.exists() || skinDir.exists()) {
throw new GradleException("Unable to generate a skin with the same neame as an existing skin: ${skinName}")
}
skinsDir.mkdirs()
// First the ${skinName}.less file
copy {
from "${rootProject.projectDir}/etc/skin/skinName.less"
into skinsDir
rename { return "${skinName}.less" }
expand(skinName: skinName)
}
// Then the contents of the ${skinName} folder
copy {
from "${rootProject.projectDir}/etc/skin/skinName"
into skinDir
expand(skinName: skinName)
}
// Copy skinList.xml if it does not exist
File skinListFile = rootProject.file("${projectDir}/src/main/webapp/media/skins/respondr/skinList.xml")
File respondrDir = rootProject.file("${projectDir}/src/main/webapp/media/skins/respondr")
if (!skinListFile.exists()) {
copy {
from "${rootProject.projectDir}/etc/skin/skinList.xml"
into respondrDir
}
}
logger.lifecycle("Generated new skin ${skinName} at the following location: ${skinsDir}")
logger.lifecycle("IMPORTANT! To use the ${skinName} skin (instead of the default) change the 'PREFdynamicSkinName' preference in dynamic-respondr-skin")
}
}
// Set up resources from custom skins so we can compile with NodeJS & lessc
boolean taskIsDataImport = project.gradle.startParameter.taskNames.any {
it.contains('dataImport')
};
if (taskIsDataImport) {
logger.lifecycle "Skipping prepareSkinResources; dataImport doesn't require compiled skin(s)"
}
else if (!skinsDir.exists()) {
logger.lifecycle "Skipping prepareSkinResources; no custom skin files defined in ${skinsDir}"
}
else {
// Step 1: Unpack the upstream uPortal.war into a work directory
task prepareSkinResources(dependsOn: npmInstall) {
String workDir = "${buildDir}/tmp/skin/uPortal"
doLast {
// Locate the uPortal.war dependency
Dependency d = configurations.runtime.dependencies.matching { it.name == 'uPortal-webapp' }.getAt(0)
File uPortalWar = configurations.runtime.files(d).getAt(0)
copy {
from zipTree(uPortalWar)
into workDir
}
}
// Step 2: Add the skin resources from within src/main
doLast {
copy {
from skinsDir
into "${workDir}/media/skins/respondr"
}
}
// Lastly, update configuration of the 'war' task to include compiled skins
war {
from("${workDir}/media/skins/respondr") {
into('media/skins/respondr')
}
}
}
String skinTmpDir = "${buildDir}/tmp/skin/uPortal/media/skins/respondr/"
// Identify custom skins located in skinsDir
logger.lifecycle "Preparing Gradle tasks to compile the following custom skin files defined in ${skinsDir}"
FileTree skinFiles = fileTree(dir: skinsDir, include: "*.less")
// Step 3: Use NodeJS & lessc to compile custom skin(sz)
skinFiles.eachWithIndex { f, index ->
String it = f.toString()
// Strip the path
String skinFileName = it.substring(it.lastIndexOf(File.separator) + 1)
logger.lifecycle " -> ${skinFileName} $index"
task "compileLess${index}"(type: NpmTask, dependsOn: prepareSkinResources) {
args = ['run', 'compile-less', "${skinTmpDir}${skinFileName}", "${skinTmpDir}${skinFileName.replace('.less', '.css')}"]
}
}
task skinDeployFiles(type: Copy) {
dependsOn project.rootProject.tasks.portalProperties
File serverBase = project.rootProject.file(project.rootProject.ext['buildProperties'].getProperty('server.home'))
logger.lifecycle("serverBase: ${serverBase}")
File deployDir = new File(serverBase, "webapps/${project.name}/media/skins/respondr")
logger.lifecycle("deployDir: ${deployDir}")
doFirst {
logger.lifecycle("Copying skin files from ${skinTmpDir} to ${deployDir}")
}
from skinTmpDir
into deployDir
}
war.dependsOn {
tasks.findAll { task -> task.name.startsWith('compileLess') }
}
}
/*
* Import/Export Support
*/
import org.apereo.portal.start.shell.PortalShellInvoker
ext {
shellDir = rootProject.file("${buildDir}/shell")
}
dataInit {
description 'Drop and recreate uPortal tables and reimport data'
/*
* Add to the scriptFile commands that drop then create then load the legacy database
* tables and data (i.e. non-Hibernate stuff that's still based on tables.xml and data.xml)
*/
doLast {
String tablesFile = '/properties/db/tables.xml'
String dataFile = '/properties/db/data.xml'
boolean droptables = true
boolean createtables = true
boolean populatetables = true
shellDir.mkdirs()
File scriptFile = rootProject.file(new File(shellDir, 'dataInit.groovy'))
scriptFile.delete() // Clear from previous invocation, if present
scriptFile.append(
"""
//db(String target, String tablesFile, String dataFile, String scriptFile, boolean dropTables, boolean createTables, boolean populateTables)
portalShellBuildHelper.db('db',
'${tablesFile}', '${dataFile}', ' ',
${droptables}, ${createtables}, ${populatetables});
""" )
}
/*
* Add to the scriptFile commands that drop then create the Hibernate-managed tables.
*/
doLast {
boolean export = true
String outputFile = ' '
File scriptFile = rootProject.file(new File(shellDir, 'dataInit.groovy'))
['PortalDb', 'RawEventsDb', 'AggrEventsDb'].each { databaseQualifier ->
scriptFile.append(
"""
//hibernateDrop(String target, String databaseQualifier, boolean export, String outputFile)
portalShellBuildHelper.hibernateDrop('db-hibernate',
'${databaseQualifier}',
${export},
/${outputFile}/);
//hibernateCreate(String target, String databaseQualifier, boolean export, String outputFile)
portalShellBuildHelper.hibernateCreate('db-hibernate',
'${databaseQualifier}',
${export},
/${outputFile}/);
""" )
}
}
/*
* Add to the scriptFile commands that import database entities in
* the folder defined by the 'base.entities.location' build property.
*/
doLast {
String baseEntitiesLocation = PortalShellInvoker.createGroovySafePath(rootProject.ext['buildProperties'].getProperty('base.entities.location'))
String implementationEntitiesLocation = PortalShellInvoker.createGroovySafePath(rootProject.ext['buildProperties'].getProperty('implementation.entities.location'))
String pattern = ' '
String file = ' '
String archive = ' '
String files = ' '
String filesListFile = ' '
String logDir = PortalShellInvoker.createGroovySafePath(buildDir.getPath())
File scriptFile = rootProject.file(new File(shellDir, 'dataInit.groovy'))
[ baseEntitiesLocation, implementationEntitiesLocation ].each { entitiesLocation ->
scriptFile.append(
"""
//dataImport(String target, String dataDir, String pattern, String filesList, String archive, String logDir)
portalShellBuildHelper.dataImport('data-import',
'${entitiesLocation}',
'${pattern}',
portalShellBuildHelper.getFilesListStringFromInput('${file}', '${files}', '${filesListFile}'),
'${archive}',
'${logDir}');
""" )
}
}
/*
* Execute the commands in the scriptFile.
*/
doLast {
File scriptFile = rootProject.file(new File(shellDir, 'dataInit.groovy'))
PortalShellInvoker psi = new PortalShellInvoker()
psi.invoke(project, scriptFile.getAbsolutePath())
}
}
dataImport {
description 'Adds to or updates the portal database for the entities defined in the specified XML file(s). Requires -Dfile={path-to-file} or -Ddir={path-to-directory}'
doLast {
// Validate inputs
Map<String,String> args = [
file: System.getProperty('file'),
dir: System.getProperty('dir'),
manifest: System.getProperty('manifest'),
archive: System.getProperty('archive')
].findAll { key, value -> value != null }
if (args.size() != 1) {
logger.lifecycle('Please specify exactly one of -Dfile={path}, -Ddir={path}, -Dmanifest={path}, or -Darchive={path}')
/*
* Stop the build by throwing the relevant exception from the org.gradle.api package
* (https://stackoverflow.com/questions/10312259/recommended-way-to-stop-a-gradle-build).
*/
throw new InvalidUserDataException('Invalid number of parameters')
} else {
// Format the arguments
String dirEscaped = args.containsKey('dir') ? PortalShellInvoker.createGroovySafePath(args['dir']) : ' '
String pattern = ' ' // Not currently in use
String fileEscaped = args.containsKey('file') ? PortalShellInvoker.createGroovySafePath(args['file']) : ' '
String filesEscaped = ' ' // Not currently in use
String manifestEscaped = args.containsKey('manifest') ? PortalShellInvoker.createGroovySafePath(args['manifest']) : ' '
String archiveEscaped = args.containsKey('archive') ? PortalShellInvoker.createGroovySafePath(args['archive']) : ' '
String logDirEscaped = PortalShellInvoker.createGroovySafePath(buildDir.getPath())
// Prepare the scriptFile
shellDir.mkdirs()
File scriptFile = rootProject.file(new File(shellDir, 'dataImport.groovy'))
scriptFile.delete() // Clear from previous invocation, if present
scriptFile.write(
"""
//dataImport(String target, String dataDir, String pattern, String filesList, String archive, String logDir)
portalShellBuildHelper.dataImport("data-import",
'${dirEscaped}',
'${pattern}',
portalShellBuildHelper.getFilesListStringFromInput('${fileEscaped}','${filesEscaped}','${manifestEscaped}'),
'${archiveEscaped}',
'${logDirEscaped}');
""" )
PortalShellInvoker psi = new PortalShellInvoker()
psi.invoke(project, scriptFile.getAbsolutePath())
}
}
}
dataExport {
description 'Creates XML files representing the requested entities and writes them to the specified file system location. Parameters: -Ddir={path-to-directory} -Dtype={entity-type} [-Dsysid={entity-identifier}]'
doLast {
// Three -D arguments may be passed; all are optional
String dir = System.getProperty('dir') ?: "${buildDir}/export"
String type = System.getProperty('type') ?: ' '
String sysid = System.getProperty('sysid') ?: ' '
String dirEscaped = PortalShellInvoker.createGroovySafePath(dir)
String logDirEscaped = PortalShellInvoker.createGroovySafePath(buildDir.getPath())
// Prepare the scriptFile
shellDir.mkdirs()
File scriptFile = rootProject.file(new File(shellDir, 'dataExport.groovy'))
scriptFile.delete() // Clear from previous invocation, if present
scriptFile.write(
"""
//dataExport(String target, String dataDir, String type, String sysid, String logDir)
portalShellBuildHelper.dataExport('data-export',
'${dirEscaped}',
'${type}',
'${sysid}',
'${logDirEscaped}');
""" )
PortalShellInvoker psi = new PortalShellInvoker()
psi.invoke(project, scriptFile.getAbsolutePath())
}
}
dataDelete {
description 'Deletes the specified entity. Requires -Dtype={entity-type} and -Dsysid={id}'
doLast {
// Validate inputs
Map<String,String> args = [
type: System.getProperty('type'),
sysid: System.getProperty('sysid')
].findAll { key, value -> value != null }
if (args.size() != 2) {
logger.lifecycle('Both -Dtype={entity-type} and -Dsysid={id} must be specified ' +
'for dataDelete; use the dataList task to determine available data types')
/*
* Stop the build by throwing the relevant exception from the org.gradle.api package
* (https://stackoverflow.com/questions/10312259/recommended-way-to-stop-a-gradle-build).
*/
throw new InvalidUserDataException('Missing type and/or sysid parameter(s)')
} else {
// Prepare the scriptFile
shellDir.mkdirs()
File scriptFile = rootProject.file(new File(shellDir, 'dataDelete.groovy'))
scriptFile.delete() // Clear from previous invocation, if present
scriptFile.write(
"""
//dataDelete(String target, String type, String sysid)
portalShellBuildHelper.dataDelete('data-delete',
'${args['type']}',
'${args['sysid']}')
""" )
PortalShellInvoker psi = new PortalShellInvoker()
psi.invoke(project, scriptFile.getAbsolutePath())
}
}
}
dataList {
description 'With no arguments (-Dtype={entity-type}) lists all supported portal data types and the operations (export, delete) supported for each. '
doLast {
// Is there a -Dtype= argument passed?
String type = System.getProperty('type') ?: ' '
// Prepare the scriptFile
shellDir.mkdirs()
File scriptFile = rootProject.file(new File(shellDir, 'dataList.groovy'))
scriptFile.delete() // Clear from previous invocation, if present
scriptFile.write(
"""
//dataList(String target, String type)
portalShellBuildHelper.dataList('data-list', '${type}');
""" )
PortalShellInvoker psi = new PortalShellInvoker()
psi.invoke(project, scriptFile.getAbsolutePath())
}
}