JAL-3562 exclude testNG groups from a build via -PtestngExcludedGroups=Not-bamboo
[jalview.git] / build.gradle
1 import org.apache.tools.ant.filters.ReplaceTokens
2 import org.gradle.internal.os.OperatingSystem
3 import org.gradle.plugins.ide.eclipse.model.Output
4 import org.gradle.plugins.ide.eclipse.model.Library
5 import java.security.MessageDigest
6 import groovy.transform.ExternalizeMethods
7 import groovy.util.XmlParser
8 import groovy.xml.XmlUtil
9
10
11 buildscript {
12   repositories {
13     mavenCentral()
14     mavenLocal()
15   }
16   dependencies {
17     classpath 'org.openclover:clover:4.4.1'
18   }
19 }
20
21
22 plugins {
23   id 'java'
24   id 'application'
25   id 'eclipse'
26   id 'com.github.johnrengelman.shadow' version '4.0.3'
27   id 'com.install4j.gradle' version '8.0.4'
28   id 'com.dorongold.task-tree' version '1.5' // only needed to display task dependency tree with  gradle task1 [task2 ...] taskTree
29 }
30
31 repositories {
32   jcenter()
33   mavenCentral()
34   mavenLocal()
35 }
36
37
38 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
39 def string(Object o) {
40   return o == null ? "" : o.toString()
41 }
42
43
44 ext {
45   jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
46   jalviewDirRelativePath = jalviewDir
47
48   // local build environment properties
49   def localProps = "${jalviewDirAbsolutePath}/local.properties"
50   if (file(localProps).exists()) {
51     try {
52       def p = new Properties()
53       def localPropsFIS = new FileInputStream(localProps)
54       p.load(localPropsFIS)
55       localPropsFIS.close()
56       p.each {
57         key, val -> 
58           def oldval = findProperty(key)
59           setProperty(key, val)
60           if (oldval != null) {
61             println("Overriding property '${key}' ('${oldval}') with local.properties value '${val}'")
62           } else {
63             println("Setting unknown property '${key}' with local.properties value '${val}'")
64           }
65       }
66     } catch (Exception e) {
67       System.out.println("Exception reading local.properties")
68     }
69   }
70
71   // this property set when running Eclipse headlessly
72   j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
73   // this property set by Eclipse
74   eclipseApplicationProperty = string("eclipse.application")
75   // CHECK IF RUNNING FROM WITHIN ECLIPSE
76   def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
77   IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
78   // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
79   if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
80     println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
81     IN_ECLIPSE = false
82   }
83   if (IN_ECLIPSE) {
84     println("WITHIN ECLIPSE IDE")
85   } else {
86     println("HEADLESS BUILD")
87   }
88   /* *-/
89   System.properties.sort { it.key }.each {
90     key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
91   }
92   /-* *-/
93   if (false && IN_ECLIPSE) {
94     jalviewDir = jalviewDirAbsolutePath
95   }
96   */
97
98   // essentials
99   bareSourceDir = string(source_dir)
100   sourceDir = string("${jalviewDir}/${bareSourceDir}")
101   resourceDir = string("${jalviewDir}/${resource_dir}")
102   bareTestSourceDir = string(test_source_dir)
103   testSourceDir = string("${jalviewDir}/${bareTestSourceDir}")
104
105   // clover
106   cloverInstrDir = file("${buildDir}/${cloverSourcesInstrDir}")
107   cloverDb = string("${buildDir}/clover/clover.db")
108   classesDir = string("${jalviewDir}/${classes_dir}")
109   if (clover.equals("true")) {
110     use_clover = true
111     classesDir = string("${buildDir}/${cloverClassesDir}")
112   } else {
113     use_clover = false
114     classesDir = string("${jalviewDir}/${classes_dir}")
115   }
116
117   classes = classesDir
118
119   getdownWebsiteDir = string("${jalviewDir}/${getdown_website_dir}/${JAVA_VERSION}")
120   buildDist = true
121
122   // the following values might be overridden by the CHANNEL switch
123   getdownChannelName = CHANNEL.toLowerCase()
124   getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
125   getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
126   getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
127   getdownAppDistDir = getdown_app_dir_alt
128   buildProperties = string("${classesDir}/${build_properties_file}")
129   reportRsyncCmd = false
130   jvlChannelName = CHANNEL.toLowerCase()
131   switch (CHANNEL) {
132
133     case "BUILD":
134     // TODO: get bamboo build artifact URL for getdown artifacts
135     getdown_channel_base = bamboo_channelbase
136     getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
137     getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
138     jvlChannelName += "_${getdownChannelName}"
139     // automatically add the test group Not-bamboo for exclusion 
140     if ("".equals(testngExcludedGroups)) { 
141       testngExcludedGroups = "Not-bamboo"
142     }
143     break
144
145     case "RELEASE":
146     getdownAppDistDir = getdown_app_dir_release
147     reportRsyncCommand = true
148     break
149
150     case "ARCHIVE":
151     getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
152     getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
153     getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
154     if (!file("${ARCHIVEDIR}/${packageDir}").exists()) {
155       throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
156     } else {
157       packageDir = string("${ARCHIVEDIR}/${packageDir}")
158       buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
159       buildDist = false
160     }
161     reportRsyncCommand = true
162     break
163
164     case "ARCHIVELOCAL":
165     getdownChannelName = string("archive/${JALVIEW_VERSION}")
166     getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
167     getdownAppBase = file(getdownWebsiteDir).toURI().toString()
168     if (!file("${ARCHIVEDIR}/${packageDir}").exists()) {
169       throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
170     } else {
171       packageDir = string("${ARCHIVEDIR}/${packageDir}")
172       buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
173       buildDist = false
174     }
175     reportRsyncCommand = true
176     getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
177     break
178
179     case "DEVELOP":
180     reportRsyncCommand = true
181     break
182
183     case "TEST-RELEASE":
184     reportRsyncCommand = true
185     break
186
187     case ~/^SCRATCH(|-[-\w]*)$/:
188     getdownChannelName = CHANNEL
189     getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
190     getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
191     reportRsyncCommand = true
192     break
193
194     case "TEST-LOCAL":
195     if (!file("${LOCALDIR}").exists()) {
196       throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
197     } else {
198       getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
199       getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
200     }
201     break
202
203     case "LOCAL":
204     getdownAppBase = file(getdownWebsiteDir).toURI().toString()
205     getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
206     break
207
208     default: // something wrong specified
209     throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
210     break
211
212   }
213   // override getdownAppBase if requested
214   if (findProperty("getdown_appbase_override") != null) {
215     getdownAppBase = string(getProperty("getdown_appbase_override"))
216     println("Overriding getdown appbase with '${getdownAppBase}'")
217   }
218   // sanitise file name for jalview launcher file for this channel
219   jvlChannelName = jvlChannelName.replaceAll(/[^\w\-]/,"_")
220
221   getdownAppDir = string("${getdownWebsiteDir}/${getdownAppDistDir}")
222   //getdownJ11libDir = "${getdownWebsiteDir}/${getdown_j11lib_dir}"
223   getdownResourceDir = string("${getdownWebsiteDir}/${getdown_resource_dir}")
224   getdownInstallDir = string("${getdownWebsiteDir}/${getdown_install_dir}")
225   getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
226   getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
227   /* compile without modules -- using classpath libraries
228   modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
229   modules_runtimeClasspath = modules_compileClasspath
230   */
231   gitHash = string("")
232   gitBranch = string("")
233
234   println("Using a ${CHANNEL} profile.")
235
236   additional_compiler_args = []
237   // configure classpath/args for j8/j11 compilation
238   if (JAVA_VERSION.equals("1.8")) {
239     JAVA_INTEGER_VERSION = string("8")
240     //libDir = j8libDir
241     libDir = j11libDir
242     libDistDir = j8libDir
243     compile_source_compatibility = 1.8
244     compile_target_compatibility = 1.8
245     // these are getdown.txt properties defined dependent on the JAVA_VERSION
246     getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
247     getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
248     // this property is assigned below and expanded to multiple lines in the getdown task
249     getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
250     // this property is for the Java library used in eclipse
251     eclipseJavaRuntimeName = string("JavaSE-1.8")
252   } else if (JAVA_VERSION.equals("11")) {
253     JAVA_INTEGER_VERSION = string("11")
254     libDir = j11libDir
255     libDistDir = j11libDir
256     compile_source_compatibility = 11
257     compile_target_compatibility = 11
258     getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
259     getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
260     getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
261     eclipseJavaRuntimeName = string("JavaSE-11")
262     /* compile without modules -- using classpath libraries
263     additional_compiler_args += [
264     '--module-path', modules_compileClasspath.asPath,
265     '--add-modules', j11modules
266     ]
267      */
268   } else if (JAVA_VERSION.equals("12") || JAVA_VERSION.equals("13")) {
269     JAVA_INTEGER_VERSION = JAVA_VERSION
270     libDir = j11libDir
271     libDistDir = j11libDir
272     compile_source_compatibility = JAVA_VERSION
273     compile_target_compatibility = JAVA_VERSION
274     getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
275     getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
276     getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
277     eclipseJavaRuntimeName = string("JavaSE-11")
278     /* compile without modules -- using classpath libraries
279     additional_compiler_args += [
280     '--module-path', modules_compileClasspath.asPath,
281     '--add-modules', j11modules
282     ]
283      */
284   } else {
285     throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
286   }
287
288
289   // for install4j
290   JAVA_MIN_VERSION = JAVA_VERSION
291   JAVA_MAX_VERSION = JAVA_VERSION
292   def jreInstallsDir = string(jre_installs_dir)
293   if (jreInstallsDir.startsWith("~/")) {
294     jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
295   }
296   macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
297   macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre-${JAVA_INTEGER_VERSION}-mac-x64.tar.gz")
298   windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
299   windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre-${JAVA_INTEGER_VERSION}-windows-x64.tar.gz")
300   linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
301   linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre-${JAVA_INTEGER_VERSION}-linux-x64.tar.gz")
302   install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
303   install4jConfFileName = string("jalview-install4j-conf.install4j")
304   install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
305   install4jHomeDir = install4j_home_dir
306   if (install4jHomeDir.startsWith("~/")) {
307     install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
308   }
309
310
311
312   buildingHTML = string("${jalviewDir}/${docDir}/building.html")
313   helpFile = string("${classesDir}/${help_dir}/help.jhm")
314   helpParentDir = string("${jalviewDir}/${help_parent_dir}")
315   helpSourceDir = string("${helpParentDir}/${help_dir}")
316
317
318   relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
319   jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
320   jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
321   if (IN_ECLIPSE) {
322     jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
323   } else {
324     jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
325   }
326   jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
327   jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
328   jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
329   jalviewjsJalviewCoreHtmlFile = string("")
330   jalviewjsJalviewCoreName = string(jalviewjs_core_name)
331   jalviewjsCoreClasslists = []
332   jalviewjsJalviewTemplateName = string(jalviewjs_name)
333   jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
334   jalviewjsJ2sProps = null
335
336   eclipseWorkspace = null
337   eclipseBinary = string("")
338   eclipseVersion = string("")
339   eclipseDebug = false
340   // ENDEXT
341 }
342
343
344 sourceSets {
345   main {
346     java {
347       srcDirs sourceDir
348       outputDir = file(classesDir)
349     }
350
351     resources {
352       srcDirs resourceDir
353       srcDirs += helpParentDir
354     }
355
356     jar.destinationDir = file("${jalviewDir}/${packageDir}")
357
358     compileClasspath = files(sourceSets.main.java.outputDir)
359     //compileClasspath += files(sourceSets.main.resources.srcDirs)
360     compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
361
362     runtimeClasspath = compileClasspath
363   }
364
365   clover {
366     java {
367       srcDirs = [ cloverInstrDir ]
368       outputDir = file("${buildDir}/${cloverClassesDir}")
369     }
370
371     resources {
372       srcDirs = sourceSets.main.resources.srcDirs
373     }
374     compileClasspath = configurations.cloverRuntime + files( sourceSets.clover.java.outputDir )
375     compileClasspath += files(sourceSets.main.java.outputDir)
376     compileClasspath += sourceSets.main.compileClasspath
377     compileClasspath += fileTree(dir: "${jalviewDir}/${utilsDir}", include: ["**/*.jar"])
378     compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
379
380     runtimeClasspath = compileClasspath
381   }
382
383   test {
384     java {
385       srcDirs testSourceDir
386       outputDir = file("${jalviewDir}/${testOutputDir}")
387     }
388
389     resources {
390       srcDirs = sourceSets.main.resources.srcDirs
391     }
392
393     compileClasspath = files( sourceSets.test.java.outputDir )
394
395     if (use_clover) {
396       compileClasspath = sourceSets.clover.compileClasspath
397     } else {
398       compileClasspath += files(sourceSets.main.java.outputDir)
399     }
400
401     compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
402     compileClasspath += fileTree(dir: "${jalviewDir}/${utilsDir}/testnglibs", include: ["**/*.jar"])
403     compileClasspath += fileTree(dir: "${jalviewDir}/${utilsDir}/testlibs", include: ["**/*.jar"])
404
405     runtimeClasspath = compileClasspath
406   }
407 }
408
409
410 // clover bits
411 dependencies {
412   if (use_clover) {
413     cloverCompile 'org.openclover:clover:4.4.1'
414     testCompile 'org.openclover:clover:4.4.1'
415   }
416 }
417
418 configurations {
419   cloverRuntime
420   cloverRuntime.extendsFrom cloverCompile
421 }
422
423
424 // eclipse project and settings files creation, also used by buildship
425 eclipse {
426   project {
427     name = eclipse_project_name
428
429     natures 'org.eclipse.jdt.core.javanature',
430     'org.eclipse.jdt.groovy.core.groovyNature',
431     'org.eclipse.buildship.core.gradleprojectnature'
432
433     buildCommand 'org.eclipse.jdt.core.javabuilder'
434     buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
435   }
436
437   classpath {
438     //defaultOutputDir = sourceSets.main.java.outputDir
439     def removeThese = []
440     configurations.each{
441       if (it.isCanBeResolved()) {
442         removeThese += it
443       }
444     }
445
446     minusConfigurations += removeThese
447     plusConfigurations = [ ]
448     file {
449
450       whenMerged { cp ->
451         def removeTheseToo = []
452         HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
453         cp.entries.each { entry ->
454           // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
455           // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
456           // we add the resources and help/help dirs in as libs afterwards (see below)
457           if (entry.kind == 'src') {
458             if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
459               removeTheseToo += entry
460             } else {
461               alreadyAddedSrcPath.putAt(entry.path, true)
462             }
463           }
464
465         }
466         cp.entries.removeAll(removeTheseToo)
467
468         //cp.entries += new Output("${eclipse_bin_dir}/main")
469         if (file(helpParentDir).isDirectory()) {
470           cp.entries += new Library(fileReference(helpParentDir))
471         }
472         if (file(resourceDir).isDirectory()) {
473           cp.entries += new Library(fileReference(resourceDir))
474         }
475
476         HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
477
478         sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
479           //don't want to add outputDir as eclipse is using its own output dir in bin/main
480           if (it.isDirectory() || ! it.exists()) {
481             // don't add dirs to classpath, especially if they don't exist
482             return false // groovy "continue" in .any closure
483           }
484           def itPath = it.toString()
485           if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
486             // make relative path
487             itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
488           }
489           if (alreadyAddedLibPath.get(itPath)) {
490             //println("Not adding duplicate entry "+itPath)
491           } else {
492             //println("Adding entry "+itPath)
493             cp.entries += new Library(fileReference(itPath))
494             alreadyAddedLibPath.put(itPath, true)
495           }
496         }
497
498         sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
499           //no longer want to add outputDir as eclipse is using its own output dir in bin/main
500           if (it.isDirectory() || ! it.exists()) {
501             // don't add dirs to classpath
502             return false // groovy "continue" in .any closure
503           }
504
505           def itPath = it.toString()
506           if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
507             itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
508           }
509           if (alreadyAddedLibPath.get(itPath)) {
510             // don't duplicate
511           } else {
512             def lib = new Library(fileReference(itPath))
513             lib.entryAttributes["test"] = "true"
514             cp.entries += lib
515             alreadyAddedLibPath.put(itPath, true)
516           }
517         }
518
519       } // whenMerged
520
521     } // file
522
523     containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
524
525   } // classpath
526
527   jdt {
528     // for the IDE, use java 11 compatibility
529     sourceCompatibility = compile_source_compatibility
530     targetCompatibility = compile_target_compatibility
531     javaRuntimeName = eclipseJavaRuntimeName
532
533     // add in jalview project specific properties/preferences into eclipse core preferences
534     file {
535       withProperties { props ->
536         def jalview_prefs = new Properties()
537         def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
538         jalview_prefs.load(ins)
539         ins.close()
540         jalview_prefs.forEach { t, v ->
541           if (props.getAt(t) == null) {
542             props.putAt(t, v)
543           }
544         }
545       }
546     }
547
548   } // jdt
549
550   if (IN_ECLIPSE) {
551     // Don't want these to be activated if in headless build
552     synchronizationTasks "eclipseSynchronizationTask"
553     autoBuildTasks "eclipseAutoBuildTask"
554
555   }
556 }
557
558
559 task cloverInstr {
560   // only instrument source, we build test classes as normal
561   inputs.files files (sourceSets.main.allJava,sourceSets.test.allJava) // , fileTree(dir:"$jalviewDir/$testSourceDir", include: ["**/*.java"]))
562   outputs.dir cloverInstrDir
563
564   doFirst {
565     delete cloverInstrDir
566     def argsList = [
567       "--initstring",
568       cloverDb,
569       "-d",
570       cloverInstrDir.getPath(),
571     ]
572     argsList.addAll(
573       inputs.files.files.collect(
574         { file -> file.absolutePath }
575       )
576     )
577     String[] args = argsList.toArray()
578     println("About to instrument "+args.length +" files")
579     com.atlassian.clover.CloverInstr.mainImpl(args)
580   }
581 }
582
583
584 cloverClasses.dependsOn cloverInstr
585
586
587 task cloverReport {
588   group = "Verification"
589   description = "Creates the Clover report"
590   inputs.dir "${buildDir}/clover"
591   outputs.dir "${reportsDir}/clover"
592   onlyIf {
593     file(cloverDb).exists()
594   }
595   doFirst {
596     def argsList = [
597       "--initstring",
598       cloverDb,
599       "-o",
600       "${reportsDir}/clover"
601     ]
602     String[] args = argsList.toArray()
603     com.atlassian.clover.reporters.html.HtmlReporter.runReport(args)
604
605     // and generate ${reportsDir}/clover/clover.xml
606     args = [
607       "--initstring",
608       cloverDb,
609       "-o",
610       "${reportsDir}/clover/clover.xml"
611     ].toArray()
612     com.atlassian.clover.reporters.xml.XMLReporter.runReport(args)
613   }
614 }
615
616
617 compileCloverJava {
618
619   doFirst {
620     sourceCompatibility = compile_source_compatibility
621     targetCompatibility = compile_target_compatibility
622     options.compilerArgs += additional_compiler_args
623     print ("Setting target compatibility to "+targetCompatibility+"\n")
624   }
625   classpath += configurations.cloverRuntime
626 }
627
628
629 task cleanClover {
630   doFirst {
631     delete cloverInstrDir
632     delete cloverDb
633   }
634 }
635 // end clover bits
636
637
638 compileJava {
639
640   doFirst {
641     sourceCompatibility = compile_source_compatibility
642     targetCompatibility = compile_target_compatibility
643     options.compilerArgs = additional_compiler_args
644     print ("Setting target compatibility to "+targetCompatibility+"\n")
645   }
646
647 }
648
649
650 compileTestJava {
651   if (use_clover) {
652     dependsOn compileCloverJava
653     classpath += configurations.cloverRuntime
654   } else {
655     classpath += sourceSets.main.runtimeClasspath
656   }
657   doFirst {
658     sourceCompatibility = compile_source_compatibility
659     targetCompatibility = compile_target_compatibility
660     options.compilerArgs = additional_compiler_args
661     print ("Setting target compatibility to "+targetCompatibility+"\n")
662   }
663 }
664
665
666 clean {
667   doFirst {
668     delete sourceSets.main.java.outputDir
669   }
670 }
671
672
673 cleanTest {
674   dependsOn cleanClover
675   doFirst {
676     delete sourceSets.test.java.outputDir
677   }
678 }
679
680
681 // format is a string like date.format("dd MMMM yyyy")
682 def getDate(format) {
683   def date = new Date()
684   return date.format(format)
685 }
686
687
688 task setGitVals {
689   def hashStdOut = new ByteArrayOutputStream()
690   exec {
691     commandLine "git", "rev-parse", "--short", "HEAD"
692     standardOutput = hashStdOut
693     ignoreExitValue true
694   }
695
696   def branchStdOut = new ByteArrayOutputStream()
697   exec {
698     commandLine "git", "rev-parse", "--abbrev-ref", "HEAD"
699     standardOutput = branchStdOut
700     ignoreExitValue true
701   }
702
703   gitHash = hashStdOut.toString().trim()
704   gitBranch = branchStdOut.toString().trim()
705
706   outputs.upToDateWhen { false }
707 }
708
709
710 task createBuildProperties(type: WriteProperties) {
711   dependsOn setGitVals
712   inputs.dir(sourceDir)
713   inputs.dir(resourceDir)
714   file(buildProperties).getParentFile().mkdirs()
715   outputFile (buildProperties)
716   // taking time specific comment out to allow better incremental builds
717   comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
718   //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
719   property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
720   property "VERSION", JALVIEW_VERSION
721   property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
722   outputs.file(outputFile)
723 }
724
725
726 task cleanBuildingHTML(type: Delete) {
727   doFirst {
728     delete buildingHTML
729   }
730 }
731
732
733 task convertBuildingMD(type: Exec) {
734   dependsOn cleanBuildingHTML
735   def buildingMD = "${jalviewDir}/${docDir}/building.md"
736   def css = "${jalviewDir}/${docDir}/github.css"
737
738   def pandoc = null
739   pandoc_exec.split(",").each {
740     if (file(it.trim()).exists()) {
741       pandoc = it.trim()
742       return true
743     }
744   }
745
746   def hostname = "hostname".execute().text.trim()
747   def buildtoolsPandoc = System.getProperty("user.home")+"/buildtools/pandoc/bin/pandoc"
748   if ((pandoc == null || ! file(pandoc).exists()) && file(buildtoolsPandoc).exists()) {
749     pandoc = System.getProperty("user.home")+"/buildtools/pandoc/bin/pandoc"
750   }
751
752   doFirst {
753     if (pandoc != null && file(pandoc).exists()) {
754         commandLine pandoc, '-s', '-o', buildingHTML, '--metadata', 'pagetitle="Building Jalview from Source"', '--toc', '-H', css, buildingMD
755     } else {
756         println("Cannot find pandoc. Skipping convert building.md to HTML")
757         throw new StopExecutionException("Cannot find pandoc. Skipping convert building.md to HTML")
758     }
759   }
760
761   ignoreExitValue true
762
763   inputs.file(buildingMD)
764   inputs.file(css)
765   outputs.file(buildingHTML)
766 }
767
768
769 clean {
770   doFirst {
771     delete buildingHTML
772   }
773 }
774
775
776 task syncDocs(type: Sync) {
777   dependsOn convertBuildingMD
778   def syncDir = "${classesDir}/${docDir}"
779   from fileTree("${jalviewDir}/${docDir}")
780   into syncDir
781
782 }
783
784
785 task copyHelp(type: Copy) {
786   def inputDir = helpSourceDir
787   def outputDir = "${classesDir}/${help_dir}"
788   from(inputDir) {
789     exclude '**/*.gif'
790     exclude '**/*.jpg'
791     exclude '**/*.png'
792     filter(ReplaceTokens,
793       beginToken: '$$',
794       endToken: '$$',
795       tokens: [
796         'Version-Rel': JALVIEW_VERSION,
797         'Year-Rel': getDate("yyyy")
798       ]
799     )
800   }
801   from(inputDir) {
802     include '**/*.gif'
803     include '**/*.jpg'
804     include '**/*.png'
805   }
806   into outputDir
807
808   inputs.dir(inputDir)
809   outputs.files(helpFile)
810   outputs.dir(outputDir)
811 }
812
813
814 task syncLib(type: Sync) {
815   def syncDir = "${classesDir}/${libDistDir}"
816   from fileTree("${jalviewDir}/${libDistDir}")
817   into syncDir
818 }
819
820
821 task syncResources(type: Sync) {
822   from resourceDir
823   include "**/*.*"
824   into "${classesDir}"
825   preserve {
826     include "**"
827   }
828 }
829
830
831 task prepare {
832   dependsOn syncResources
833   dependsOn syncDocs
834   dependsOn copyHelp
835 }
836
837
838 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
839 test {
840   dependsOn prepare
841   dependsOn compileJava
842   if (use_clover) {
843     dependsOn cloverInstr
844   }
845
846   if (use_clover) {
847     print("Running tests " + (use_clover?"WITH":"WITHOUT") + " clover [clover="+use_clover+"]\n")
848   }
849
850   useTestNG() {
851     includeGroups testngGroups
852     excludeGroups testngExcludedGroups
853     preserveOrder true
854     useDefaultListeners=true
855   }
856
857   maxHeapSize = "1024m"
858
859   workingDir = jalviewDir
860   //systemProperties 'clover.jar' System.properties.clover.jar
861   sourceCompatibility = compile_source_compatibility
862   targetCompatibility = compile_target_compatibility
863   jvmArgs += additional_compiler_args
864
865 }
866
867
868 task buildIndices(type: JavaExec) {
869   dependsOn copyHelp
870   classpath = sourceSets.main.compileClasspath
871   main = "com.sun.java.help.search.Indexer"
872   workingDir = "${classesDir}/${help_dir}"
873   def argDir = "html"
874   args = [ argDir ]
875   inputs.dir("${workingDir}/${argDir}")
876
877   outputs.dir("${classesDir}/doc")
878   outputs.dir("${classesDir}/help")
879   outputs.file("${workingDir}/JavaHelpSearch/DOCS")
880   outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
881   outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
882   outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
883   outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
884   outputs.file("${workingDir}/JavaHelpSearch/TMAP")
885 }
886
887
888 task compileLinkCheck(type: JavaCompile) {
889   options.fork = true
890   classpath = files("${jalviewDir}/${utilsDir}")
891   destinationDir = file("${jalviewDir}/${utilsDir}")
892   source = fileTree(dir: "${jalviewDir}/${utilsDir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
893
894   inputs.file("${jalviewDir}/${utilsDir}/HelpLinksChecker.java")
895   inputs.file("${jalviewDir}/${utilsDir}/HelpLinksChecker.java")
896   outputs.file("${jalviewDir}/${utilsDir}/HelpLinksChecker.class")
897   outputs.file("${jalviewDir}/${utilsDir}/BufferedLineReader.class")
898 }
899
900
901 task linkCheck(type: JavaExec) {
902   dependsOn prepare, compileLinkCheck
903
904   def helpLinksCheckerOutFile = file("${jalviewDir}/${utilsDir}/HelpLinksChecker.out")
905   classpath = files("${jalviewDir}/${utilsDir}")
906   main = "HelpLinksChecker"
907   workingDir = jalviewDir
908   args = [ "${classesDir}/${help_dir}", "-nointernet" ]
909
910   def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
911   def errFOS = outFOS
912   standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
913     outFOS,
914     standardOutput)
915   errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
916     outFOS,
917     errorOutput)
918
919   inputs.dir("${classesDir}/${help_dir}")
920   outputs.file(helpLinksCheckerOutFile)
921 }
922
923 // import the pubhtmlhelp target
924 ant.properties.basedir = "${jalviewDir}"
925 ant.properties.helpBuildDir = "${jalviewDirAbsolutePath}/${classes_dir}/${help_dir}"
926 ant.importBuild "${utilsDir}/publishHelp.xml"
927
928
929 task cleanPackageDir(type: Delete) {
930   doFirst {
931     delete fileTree(dir: "${jalviewDir}/${packageDir}", include: "*.jar")
932   }
933 }
934
935 jar {
936   dependsOn linkCheck
937   dependsOn buildIndices
938   dependsOn createBuildProperties
939
940   manifest {
941     attributes "Main-Class": mainClass,
942     "Permissions": "all-permissions",
943     "Application-Name": "Jalview Desktop",
944     "Codebase": application_codebase
945   }
946
947   destinationDir = file("${jalviewDir}/${packageDir}")
948   archiveName = rootProject.name+".jar"
949
950   exclude "cache*/**"
951   exclude "*.jar"
952   exclude "*.jar.*"
953   exclude "**/*.jar"
954   exclude "**/*.jar.*"
955
956   inputs.dir(classesDir)
957   outputs.file("${jalviewDir}/${packageDir}/${archiveName}")
958 }
959
960
961 task copyJars(type: Copy) {
962   from fileTree(dir: classesDir, include: "**/*.jar").files
963   into "${jalviewDir}/${packageDir}"
964 }
965
966
967 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
968 task syncJars(type: Sync) {
969   from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
970   into "${jalviewDir}/${packageDir}"
971   preserve {
972     include jar.archiveName
973   }
974 }
975
976
977 task makeDist {
978   group = "build"
979   description = "Put all required libraries in dist"
980   // order of "cleanPackageDir", "copyJars", "jar" important!
981   jar.mustRunAfter cleanPackageDir
982   syncJars.mustRunAfter cleanPackageDir
983   dependsOn cleanPackageDir
984   dependsOn syncJars
985   dependsOn jar
986   outputs.dir("${jalviewDir}/${packageDir}")
987 }
988
989
990 task cleanDist {
991   dependsOn cleanPackageDir
992   dependsOn cleanTest
993   dependsOn clean
994 }
995
996 shadowJar {
997   group = "distribution"
998   if (buildDist) {
999     dependsOn makeDist
1000   }
1001   from ("${jalviewDir}/${libDistDir}") {
1002     include("*.jar")
1003   }
1004   manifest {
1005     attributes 'Implementation-Version': JALVIEW_VERSION
1006   }
1007   mainClassName = shadowJarMainClass
1008   mergeServiceFiles()
1009   classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1010   minimize()
1011 }
1012
1013
1014 task getdownWebsite() {
1015   group = "distribution"
1016   description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1017   if (buildDist) {
1018     dependsOn makeDist
1019   }
1020
1021   def getdownWebsiteResourceFilenames = []
1022   def getdownTextString = ""
1023   def getdownResourceDir = getdownResourceDir
1024   def getdownResourceFilenames = []
1025
1026   doFirst {
1027     // clean the getdown website and files dir before creating getdown folders
1028     delete getdownWebsiteDir
1029     delete getdownFilesDir
1030
1031     copy {
1032       from buildProperties
1033       rename(build_properties_file, getdown_build_properties)
1034       into getdownAppDir
1035     }
1036     getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1037
1038     // go through properties looking for getdown_txt_...
1039     def props = project.properties.sort { it.key }
1040     if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1041       props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1042     }
1043     if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1044       props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1045     }
1046     if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1047       props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1048     }
1049
1050     props.put("getdown_txt_appbase", getdownAppBase)
1051     props.each{ prop, val ->
1052       if (prop.startsWith("getdown_txt_") && val != null) {
1053         if (prop.startsWith("getdown_txt_multi_")) {
1054           def key = prop.substring(18)
1055           val.split(",").each{ v ->
1056             def line = "${key} = ${v}\n"
1057             getdownTextString += line
1058           }
1059         } else {
1060           // file values rationalised
1061           if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1062             def r = null
1063             if (val.indexOf('/') == 0) {
1064               // absolute path
1065               r = file(val)
1066             } else if (val.indexOf('/') > 0) {
1067               // relative path (relative to jalviewDir)
1068               r = file( "${jalviewDir}/${val}" )
1069             }
1070             if (r.exists()) {
1071               val = "${getdown_resource_dir}/" + r.getName()
1072               getdownWebsiteResourceFilenames += val
1073               getdownResourceFilenames += r.getPath()
1074             }
1075           }
1076           if (! prop.startsWith("getdown_txt_resource")) {
1077             def line = prop.substring(12) + " = ${val}\n"
1078             getdownTextString += line
1079           }
1080         }
1081       }
1082     }
1083
1084     getdownWebsiteResourceFilenames.each{ filename ->
1085       getdownTextString += "resource = ${filename}\n"
1086     }
1087     getdownResourceFilenames.each{ filename ->
1088       copy {
1089         from filename
1090         into getdownResourceDir
1091       }
1092     }
1093
1094     def codeFiles = []
1095     fileTree(file(packageDir)).each{ f ->
1096       if (f.isDirectory()) {
1097         def files = fileTree(dir: f, include: ["*"]).getFiles()
1098         codeFiles += files
1099       } else if (f.exists()) {
1100         codeFiles += f
1101       }
1102     }
1103     codeFiles.sort().each{f ->
1104       def name = f.getName()
1105       def line = "code = ${getdownAppDistDir}/${name}\n"
1106       getdownTextString += line
1107       copy {
1108         from f.getPath()
1109         into getdownAppDir
1110       }
1111     }
1112
1113     // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
1114     /*
1115     if (JAVA_VERSION.equals("11")) {
1116     def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
1117     j11libFiles.sort().each{f ->
1118     def name = f.getName()
1119     def line = "code = ${getdown_j11lib_dir}/${name}\n"
1120     getdownTextString += line
1121     copy {
1122     from f.getPath()
1123     into getdownJ11libDir
1124     }
1125     }
1126     }
1127      */
1128
1129     // getdown-launcher.jar should not be in main application class path so the main application can move it when updated.  Listed as a resource so it gets updated.
1130     //getdownTextString += "class = " + file(getdownLauncher).getName() + "\n"
1131     getdownTextString += "resource = ${getdown_launcher_new}\n"
1132     getdownTextString += "class = ${mainClass}\n"
1133
1134     def getdown_txt = file("${getdownWebsiteDir}/getdown.txt")
1135     getdown_txt.write(getdownTextString)
1136
1137     def getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
1138     def launchJvl = file("${getdownWebsiteDir}/${getdownLaunchJvl}")
1139     launchJvl.write("appbase="+props.get("getdown_txt_appbase"))
1140
1141     copy {
1142       from getdownLauncher
1143       rename(file(getdownLauncher).getName(), getdown_launcher_new)
1144       into getdownWebsiteDir
1145     }
1146
1147     copy {
1148       from getdownLauncher
1149       if (file(getdownLauncher).getName() != getdown_launcher) {
1150         rename(file(getdownLauncher).getName(), getdown_launcher)
1151       }
1152       into getdownWebsiteDir
1153     }
1154
1155     if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
1156       copy {
1157         from getdown_txt
1158         from getdownLauncher
1159         from "${getdownWebsiteDir}/${getdown_build_properties}"
1160         if (file(getdownLauncher).getName() != getdown_launcher) {
1161           rename(file(getdownLauncher).getName(), getdown_launcher)
1162         }
1163         into getdownInstallDir
1164       }
1165
1166       copy {
1167         from getdownInstallDir
1168         into getdownFilesInstallDir
1169       }
1170     }
1171
1172     copy {
1173       from getdown_txt
1174       from launchJvl
1175       from getdownLauncher
1176       from "${getdownWebsiteDir}/${getdown_build_properties}"
1177       if (file(getdownLauncher).getName() != getdown_launcher) {
1178         rename(file(getdownLauncher).getName(), getdown_launcher)
1179       }
1180       into getdownFilesDir
1181     }
1182
1183     copy {
1184       from getdownResourceDir
1185       into "${getdownFilesDir}/${getdown_resource_dir}"
1186     }
1187   }
1188
1189   if (buildDist) {
1190     inputs.dir("${jalviewDir}/${packageDir}")
1191   }
1192   outputs.dir(getdownWebsiteDir)
1193   outputs.dir(getdownFilesDir)
1194 }
1195
1196
1197 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
1198 task getdownDigestDir(type: JavaExec) {
1199   def digestDirPropertyName = "DIGESTDIR"
1200   description = "Digest a local dir (-P${digestDirPropertyName}=...) for getdown"
1201   doFirst {
1202     classpath = files(getdownLauncher)
1203     def digestDir = findProperty(digestDirPropertyName)
1204     if (digestDir == null) {
1205       throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
1206     }
1207     args digestDir
1208   }
1209   main = "com.threerings.getdown.tools.Digester"
1210 }
1211
1212
1213 task getdownDigest(type: JavaExec) {
1214   group = "distribution"
1215   description = "Digest the getdown website folder"
1216   dependsOn getdownWebsite
1217   doFirst {
1218     classpath = files(getdownLauncher)
1219   }
1220   main = "com.threerings.getdown.tools.Digester"
1221   args getdownWebsiteDir
1222   inputs.dir(getdownWebsiteDir)
1223   outputs.file("${getdownWebsiteDir}/digest2.txt")
1224 }
1225
1226
1227 task getdown() {
1228   group = "distribution"
1229   description = "Create the minimal and full getdown app folder for installers and website and create digest file"
1230   dependsOn getdownDigest
1231   doLast {
1232     if (reportRsyncCommand) {
1233       def fromDir = getdownWebsiteDir + (getdownWebsiteDir.endsWith('/')?'':'/')
1234       def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
1235       println "LIKELY RSYNC COMMAND:"
1236       println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
1237       if (RUNRSYNC == "true") {
1238         exec {
1239           commandLine "mkdir", "-p", toDir
1240         }
1241         exec {
1242           commandLine "rsync", "-avh", "--delete", fromDir, toDir
1243         }
1244       }
1245     }
1246   }
1247 }
1248
1249
1250 clean {
1251   doFirst {
1252     delete getdownWebsiteDir
1253     delete getdownFilesDir
1254   }
1255 }
1256
1257
1258 install4j {
1259   if (file(install4jHomeDir).exists()) {
1260     // good to go!
1261   } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
1262     install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
1263   } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
1264     install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
1265   }
1266   installDir(file(install4jHomeDir))
1267
1268   mediaTypes = Arrays.asList(install4j_media_types.split(","))
1269 }
1270
1271
1272 task copyInstall4jTemplate {
1273   def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
1274   def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
1275   inputs.file(install4jTemplateFile)
1276   inputs.file(install4jFileAssociationsFile)
1277   outputs.file(install4jConfFile)
1278
1279   doLast {
1280     def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
1281
1282     // turn off code signing if no OSX_KEYPASS
1283     if (OSX_KEYPASS == "") {
1284       install4jConfigXml.'**'.codeSigning.each { codeSigning ->
1285         codeSigning.'@macEnabled' = "false"
1286       }
1287       install4jConfigXml.'**'.windows.each { windows ->
1288         windows.'@runPostProcessor' = "false"
1289       }
1290     }
1291
1292     // turn off checksum creation for LOCAL channel
1293     def e = install4jConfigXml.application[0]
1294     if (CHANNEL == "LOCAL") {
1295       e.'@createChecksums' = "false"
1296     } else {
1297       e.'@createChecksums' = "true"
1298     }
1299
1300     // put file association actions where placeholder action is
1301     def install4jFileAssociationsText = install4jFileAssociationsFile.text
1302     def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
1303     install4jConfigXml.'**'.action.any { a ->
1304       if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
1305         def parent = a.parent()
1306         parent.remove(a)
1307         fileAssociationActions.each { faa ->
1308             parent.append(faa)
1309         }
1310         // don't need to continue in .any loop once replacements have been made
1311         return true
1312       }
1313     }
1314
1315     // write install4j file
1316     install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
1317   }
1318 }
1319
1320
1321 clean {
1322   doFirst {
1323     delete install4jConfFile
1324   }
1325 }
1326
1327
1328 task installers(type: com.install4j.gradle.Install4jTask) {
1329   group = "distribution"
1330   description = "Create the install4j installers"
1331   dependsOn setGitVals
1332   dependsOn getdown
1333   dependsOn copyInstall4jTemplate
1334
1335   projectFile = install4jConfFile
1336
1337   // create an md5 for the input files to use as version for install4j conf file
1338   def digest = MessageDigest.getInstance("MD5")
1339   digest.update(
1340     (file("${install4jDir}/${install4j_template}").text + 
1341     file("${install4jDir}/${install4j_info_plist_file_associations}").text +
1342     file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
1343   def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
1344   if (filesMd5.length() >= 8) {
1345     filesMd5 = filesMd5.substring(0,8)
1346   }
1347   def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
1348   // make install4jBuildDir relative to jalviewDir
1349   def install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
1350
1351   variables = [
1352     'JALVIEW_NAME': getdown_txt_title,
1353     'JALVIEW_DIR': "../..",
1354     'OSX_KEYSTORE': OSX_KEYSTORE,
1355     'JSIGN_SH': JSIGN_SH,
1356     'JRE_DIR': getdown_app_dir_java,
1357     'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
1358     'JALVIEW_VERSION': JALVIEW_VERSION,
1359     'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
1360     'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
1361     'JAVA_VERSION': JAVA_VERSION,
1362     'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
1363     'VERSION': JALVIEW_VERSION,
1364     'MACOS_JAVA_VM_DIR': macosJavaVMDir,
1365     'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
1366     'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
1367     'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
1368     'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
1369     'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
1370     'COPYRIGHT_MESSAGE': install4j_copyright_message,
1371     'MACOS_BUNDLE_ID': install4j_macOS_bundle_id,
1372     'INSTALLER_NAME': install4j_installer_name,
1373     'INSTALL4J_UTILS_DIR': install4j_utils_dir,
1374     'GETDOWN_WEBSITE_DIR': getdown_website_dir,
1375     'GETDOWN_FILES_DIR': getdown_files_dir,
1376     'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
1377     'GETDOWN_DIST_DIR': getdownAppDistDir,
1378     'GETDOWN_ALT_DIR': getdown_app_dir_alt,
1379     'GETDOWN_INSTALL_DIR': getdown_install_dir,
1380     'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
1381     'BUILD_DIR': install4jBuildDir,
1382   ]
1383
1384   destination = "${jalviewDir}/${install4jBuildDir}"
1385   buildSelected = true
1386
1387   if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
1388     faster = true
1389     disableSigning = true
1390   }
1391
1392   if (OSX_KEYPASS) {
1393     macKeystorePassword = OSX_KEYPASS
1394   }
1395
1396   doFirst {
1397     println("Using projectFile "+projectFile)
1398   }
1399
1400   inputs.dir(getdownWebsiteDir)
1401   inputs.file(install4jConfFile)
1402   inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
1403   inputs.dir(macosJavaVMDir)
1404   inputs.dir(windowsJavaVMDir)
1405   outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
1406 }
1407
1408
1409 task sourceDist(type: Tar) {
1410   
1411   def VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
1412   def outputFileName = "${project.name}_${VERSION_UNDERSCORES}.tar.gz"
1413   // cater for buildship < 3.1 [3.0.1 is max version in eclipse 2018-09]
1414   try {
1415     archiveFileName = outputFileName
1416   } catch (Exception e) {
1417     archiveName = outputFileName
1418   }
1419   
1420   compression Compression.GZIP
1421   
1422   into project.name
1423
1424   def EXCLUDE_FILES=[
1425     "build/*",
1426     "bin/*",
1427     "test-output/",
1428     "test-reports",
1429     "tests",
1430     "clover*/*",
1431     ".*",
1432     "benchmarking/*",
1433     "**/.*",
1434     "*.class",
1435     "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
1436     "*locales/**",
1437     "utils/InstallAnywhere",
1438     "**/*.log",
1439   ] 
1440   def PROCESS_FILES=[
1441     "AUTHORS",
1442     "CITATION",
1443     "FEATURETODO",
1444     "JAVA-11-README",
1445     "FEATURETODO",
1446     "LICENSE",
1447     "**/README",
1448     "RELEASE",
1449     "THIRDPARTYLIBS",
1450     "TESTNG",
1451     "build.gradle",
1452     "gradle.properties",
1453     "**/*.java",
1454     "**/*.html",
1455     "**/*.xml",
1456     "**/*.gradle",
1457     "**/*.groovy",
1458     "**/*.properties",
1459     "**/*.perl",
1460     "**/*.sh",
1461   ]
1462   def INCLUDE_FILES=[
1463     ".settings/org.eclipse.jdt.core.jalview.prefs",
1464   ]
1465
1466   from(jalviewDir) {
1467     exclude (EXCLUDE_FILES)
1468     include (PROCESS_FILES)
1469     filter(ReplaceTokens,
1470       beginToken: '$$',
1471       endToken: '$$',
1472       tokens: [
1473         'Version-Rel': JALVIEW_VERSION,
1474         'Year-Rel': getDate("yyyy")
1475       ]
1476     )
1477   }
1478   from(jalviewDir) {
1479     exclude (EXCLUDE_FILES)
1480     exclude (PROCESS_FILES)
1481     exclude ("appletlib")
1482     exclude ("**/*locales")
1483     exclude ("*locales/**")
1484     exclude ("utils/InstallAnywhere")
1485
1486     exclude (getdown_files_dir)
1487     exclude (getdown_website_dir)
1488
1489     // exluding these as not using jars as modules yet
1490     exclude ("$j11modDir/**/*.jar")
1491   }
1492   from(jalviewDir) {
1493     include(INCLUDE_FILES)
1494   }
1495 //  from (jalviewDir) {
1496 //    // explicit includes for stuff that seemed to not get included
1497 //    include(fileTree("test/**/*."))
1498 //    exclude(EXCLUDE_FILES)
1499 //    exclude(PROCESS_FILES)
1500 //  }
1501 }
1502
1503
1504 task helppages {
1505   dependsOn copyHelp
1506   dependsOn pubhtmlhelp
1507   
1508   inputs.dir("${classesDir}/${help_dir}")
1509   outputs.dir("${buildDir}/distributions/${help_dir}")
1510 }
1511
1512 // LARGE AMOUNT OF JALVIEWJS STUFF DELETED HERE
1513 task eclipseAutoBuildTask {}
1514 task eclipseSynchronizationTask {}