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