Merge branch 'task/JAL-3225_Integration_Gradle_building_into_Eclipse' into bug/JAL...
[jalview.git] / build.gradle
1 import org.apache.tools.ant.filters.ReplaceTokens
2 import org.gradle.internal.os.OperatingSystem
3
4 buildscript {
5   dependencies {
6         classpath 'org.openclover:clover:4.3.1'
7         classpath 'org.apache.commons:commons-compress:1.18'
8   }
9 }
10
11 plugins {
12   id 'java'
13   id 'application'
14   id 'eclipse'
15   id 'com.github.johnrengelman.shadow' version '4.0.3'
16   id 'com.install4j.gradle' version '7.0.9'
17 }
18
19 repositories {
20   jcenter()
21   mavenCentral()
22   mavenLocal()
23   flatDir {
24     dirs gradlePluginsDir
25   }
26 }
27
28 mainClassName = launcherClass
29 def cloverInstrDir = file("$buildDir/$cloverSourcesInstrDir")
30 def classes = "$jalviewDir/$classesDir"
31
32 if (clover.equals("true")) {
33   use_clover = true
34   classes = "$buildDir/$cloverClassesDir"
35 } else {
36   use_clover = false
37   classes = "$jalviewDir/$classesDir"
38 }
39
40 // configure classpath/args for j8/j11 compilation
41
42 def libDir
43 def libDistDir
44 def compile_source_compatibility
45 def compile_target_compatibility
46
47 ext {
48   // where the getdown channel will be built. 
49   // TODO: consider allowing this expression to  be overrriden by -P arg
50   getdownWebsiteDir = jalviewDir + '/' + getdown_website_dir + '/' + JAVA_VERSION + '/'
51   getdownAppDir = getdownWebsiteDir + '/' + getdown_app_dir
52   getdownJ11libDir = getdownWebsiteDir + '/' + getdown_j11lib_dir
53   getdownResourceDir = getdownWebsiteDir + '/' + getdown_resource_dir
54   getdownLauncher = jalviewDir + '/' + getdown_launcher
55   getdownFilesDir = jalviewDir + '/' + getdown_files_dir
56   getdownLib1 = jalviewDir + '/' + getdown_lib1
57   def getdownChannel = getdown_channel_name
58   if (getdown_channel_name.equals("COMMIT")) {
59     getdownChannel = getGitHash()
60   }
61   getdown_app_base = getdown_channel_base+"/"+getdownChannel+"/"+JAVA_VERSION+"/"
62   modules_compileClasspath = fileTree(dir: "$jalviewDir/$j11modDir", include: ["*.jar"])
63   modules_runtimeClasspath = modules_compileClasspath
64 }
65
66 def additional_compiler_args = []
67 // these are getdown.txt properties defined dependent on the JAVA_VERSION 
68 def getdown_alt_java_min_version
69 // this property is assigned below and expanded to multiple lines in the getdown task
70 def getdown_alt_multi_java_location
71 if (JAVA_VERSION.equals("1.8")) {
72   libDir = j11libDir
73   libDistDir = j8libDir
74   compile_source_compatibility = 1.8
75   compile_target_compatibility = 1.8
76   getdown_alt_java_min_version = getdown_alt_java8_min_version
77   getdown_alt_multi_java_location = getdown_alt_java8_txt_multi_java_location
78 } else if (JAVA_VERSION.equals("11")) {
79   libDir = j11libDir
80   libDistDir = j11libDir
81   compile_source_compatibility = 11
82   compile_target_compatibility = 11
83   getdown_alt_java_min_version = getdown_alt_java11_min_version
84   getdown_alt_multi_java_location = getdown_alt_java11_txt_multi_java_location
85   additional_compiler_args += [
86     '--module-path', ext.modules_compileClasspath.asPath,
87     '--add-modules', j11modules
88   ]
89 } else {
90   throw new GradleException("JAVA_VERSION=$JAVA_VERSION not currently supported by Jalview")
91 }
92
93 sourceSets {
94
95   main {
96     java {
97       srcDirs "$jalviewDir/$sourceDir"
98       outputDir = file("$classes")
99     }
100
101     resources {
102       srcDirs "$jalviewDir/$resourceDir"
103       srcDirs "$jalviewDir/$libDistDir"
104     }
105
106     jar.destinationDir = file("$jalviewDir/$packageDir")
107
108     compileClasspath = files(sourceSets.main.java.outputDir)
109     compileClasspath += fileTree(dir: "$jalviewDir/$libDir", include: ["*.jar"])
110
111     runtimeClasspath = compileClasspath
112   }
113   clover {
114     java {
115         srcDirs = [ cloverInstrDir ]
116         outputDir = file("${buildDir}/${cloverClassesDir}")
117     }
118     
119     resources {
120       srcDirs = sourceSets.main.resources.srcDirs
121     }
122     compileClasspath = configurations.cloverRuntime + files( sourceSets.clover.java.outputDir )
123     compileClasspath += files(sourceSets.main.java.outputDir)
124     compileClasspath += sourceSets.main.compileClasspath
125     compileClasspath += fileTree(dir: "$jalviewDir/$utilsDir", include: ["**/*.jar"])
126     compileClasspath += fileTree(dir: "$jalviewDir/$libDir", include: ["*.jar"])
127
128     runtimeClasspath = compileClasspath
129   }
130   
131   test {
132     java {
133       srcDirs "$jalviewDir/$testSourceDir"
134       outputDir = file("$jalviewDir/$testOutputDir")
135     }
136
137     resources {
138       srcDirs = sourceSets.main.resources.srcDirs
139     }
140
141     compileClasspath = files( sourceSets.test.java.outputDir ) 
142
143     if (use_clover) {
144       compileClasspath += sourceSets.clover.compileClasspath
145     } else {
146       compileClasspath += files(sourceSets.main.java.outputDir)
147     }
148     compileClasspath += sourceSets.main.compileClasspath
149     compileClasspath += files( sourceSets.main.resources.srcDirs)
150     compileClasspath += fileTree(dir: "$jalviewDir/$utilsDir", include: ["**/*.jar"])
151     compileClasspath += fileTree(dir: "$jalviewDir/$libDir", include: ["*.jar"])
152
153     runtimeClasspath = compileClasspath
154   }
155 }
156
157 // clover bits
158 dependencies {
159   if (use_clover) {
160     cloverCompile 'org.openclover:clover:4.3.1'
161     testCompile 'org.openclover:clover:4.3.1'
162   }
163 }
164
165 configurations {
166     cloverRuntime
167     cloverRuntime.extendsFrom cloverCompile
168 }
169
170 eclipse {
171   project {
172     name = "Jalview with gradle build"
173
174     natures 'org.eclipse.jdt.core.javanature',
175         'org.eclipse.jdt.groovy.core.groovyNature',
176         'org.eclipse.buildship.core.gradleprojectnature'
177
178     buildCommand 'org.eclipse.jdt.core.javabuilder'
179     buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
180   }
181
182   classpath {
183     //defaultOutputDir = sourceSets.main.java.outputDir
184     def removeThese = []
185     configurations.each{ if (it.isCanBeResolved()) {
186         removeThese += it
187       }
188     }
189     containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
190     
191     minusConfigurations += removeThese
192     plusConfigurations = [ ]
193     file {
194
195       whenMerged { cp ->
196         def removeTheseToo = []
197         HashMap<String, Boolean> addedSrcPath = new HashMap<>();
198         cp.entries.each { entry ->
199           if (entry.kind == 'src') {
200             if (addedSrcPath.getAt(entry.path) || !(entry.path == "src" || entry.path == "test" || entry.path == "resources")) {
201               removeTheseToo += entry
202             } else {
203               addedSrcPath.putAt(entry.path, true)
204             }
205           }
206         }
207         cp.entries.removeAll(removeTheseToo)
208       }
209       
210       withXml {
211         def node = it.asNode()
212         def srcTestAttributes
213         node.children().each{ cpe ->
214           def attributes = cpe.attributes()
215           if (attributes.get("kind") == "src" && attributes.get("path") == "test") {
216             srcTestAttributes = cpe.find { a -> a.name() == "attributes" }
217             return
218           }
219         }
220         def addTestAttribute = true
221         srcTestAttributes.each{a ->
222           if (a.name() == "attribute" && a.attributes().getAt("name") == "test") {
223             addTestAttribute = false
224           }
225         }
226         if (addTestAttribute) {
227           srcTestAttributes.append(new Node(null, "attribute", [name:"test", value:"true"]))
228         }
229         
230         node.appendNode('classpathentry', [kind:"output", path:"bin/main"])
231         HashMap<String, Boolean> addedLibPath = new HashMap<>();
232         def allPaths = sourceSets.test.compileClasspath + sourceSets.main.compileClasspath
233         sourceSets.main.compileClasspath.each{
234           //if ((it.isDirectory() || ! it.exists()) && ! (it.equals(sourceSets.main.java.outputDir))) {
235           //no longer want to add outputDir as eclipse is using its own output dir in bin/main
236           if (it.isDirectory() || ! it.exists()) {
237             // don't add dirs to classpath
238             //println("Not adding directory "+it)
239             return
240           }
241           def itPath = it.toString()
242           if (itPath.startsWith(jalviewDirAbsolutePath+"/")) {
243             itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
244           }
245           if (addedLibPath.get(itPath)) {
246             //println("Not adding duplicate entry "+itPath)
247           } else {
248             //println("Adding entry "+itPath)
249             node.appendNode('classpathentry', [kind:"lib", path:itPath])
250             addedLibPath.put(itPath, true)
251           }
252         }
253         sourceSets.test.compileClasspath.each{
254           //if ((it.isDirectory() || ! it.exists()) && ! (it.equals(sourceSets.main.java.outputDir))) {
255           //no longer want to add outputDir as eclipse is using its own output dir in bin/main
256           if (it.isDirectory() || ! it.exists()) {
257             // don't add dirs to classpath
258             //println("Not adding directory "+it)
259             return
260           }
261           def itPath = it.toString()
262           if (itPath.startsWith(jalviewDirAbsolutePath+"/")) {
263             itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
264           }
265           if (addedLibPath.get(itPath)) {
266             //println("Not adding duplicate entry "+itPath)
267           } else {
268             //println("Adding entry "+itPath)
269             node.appendNode('classpathentry', [kind:"lib", path:itPath])
270               .appendNode('attributes')
271                 .appendNode('attribute', [name:"test", value:"true"])
272             addedLibPath.put(itPath, true)
273           }
274         }
275       }
276
277     }
278   }
279
280   jdt {
281     // for the IDE, use java 11 compatibility
282     sourceCompatibility = 11
283     targetCompatibility = 11
284     javaRuntimeName = "JavaSE-11"
285
286     file {
287       withProperties { props ->
288         def jalview_prefs = new Properties()
289                 def ins = new FileInputStream(eclipse_extra_jdt_prefs_file)
290                 jalview_prefs.load(ins)
291                 ins.close()
292                 jalview_prefs.forEach { t, v ->
293                         if (props.getAt(t) == null) {
294                                 props.putAt(t, v)
295                         }
296                 }
297       }
298     }
299   }
300
301 }
302
303 task cloverInstr() {
304   // only instrument source, we build test classes as normal
305     inputs.files files (sourceSets.main.allJava) // , fileTree(dir:"$jalviewDir/$testSourceDir", include: ["**/*.java"]))
306     outputs.dir cloverInstrDir
307
308     doFirst {
309         delete cloverInstrDir
310         def argsList = ["--initstring", "${buildDir}/clover/clover.db",
311                         "-d", "${buildDir}/${cloverSourcesInstrDir}"]
312         argsList.addAll(inputs.files.files.collect({ file ->
313             file.absolutePath
314         }))
315         String[] args = argsList.toArray()
316         println("About to instrument "+args.length +" files")
317         com.atlassian.clover.CloverInstr.mainImpl(args)
318     }
319 }
320
321  
322 task cloverReport {
323         group = "Verification"
324         description = "Createst the Clover report"
325     inputs.dir "${buildDir}/clover"
326     outputs.dir "${reportsDir}/clover"
327     onlyIf {
328         file("${buildDir}/clover/clover.db").exists()
329     }
330     doFirst {
331         def argsList = ["--initstring", "${buildDir}/clover/clover.db",
332                         "-o", "${reportsDir}/clover"]
333         String[] args = argsList.toArray()
334         com.atlassian.clover.reporters.html.HtmlReporter.runReport(args)
335         
336         // and generate ${reportsDir}/clover/clover.xml
337         args = ["--initstring", "${buildDir}/clover/clover.db",
338                         "-o", "${reportsDir}/clover/clover.xml"].toArray()
339         com.atlassian.clover.reporters.xml.XMLReporter.runReport(args)
340     }
341 }
342
343 // end clover bits
344
345
346 compileJava {
347
348   doFirst {
349     sourceCompatibility = compile_source_compatibility
350     targetCompatibility = compile_target_compatibility
351     options.compilerArgs = additional_compiler_args
352     print ("Setting target compatibility to "+targetCompatibility+"\n")
353   }
354
355 }
356
357 compileTestJava {
358   if (use_clover) {
359     dependsOn compileCloverJava
360     classpath += configurations.cloverRuntime
361   } else {
362     classpath += sourceSets.main.runtimeClasspath
363   }
364   doFirst {
365     sourceCompatibility = compile_source_compatibility
366     targetCompatibility = compile_target_compatibility
367     options.compilerArgs = additional_compiler_args
368     print ("Setting target compatibility to "+targetCompatibility+"\n")
369   }
370 }
371
372
373 compileCloverJava {
374
375   doFirst {
376     sourceCompatibility = compile_source_compatibility
377     targetCompatibility = compile_target_compatibility
378     options.compilerArgs += additional_compiler_args
379     print ("Setting target compatibility to "+targetCompatibility+"\n")
380   }
381   classpath += configurations.cloverRuntime
382 }
383
384 clean {
385   delete sourceSets.main.java.outputDir
386 }
387
388 cleanTest {
389   delete sourceSets.test.java.outputDir
390   delete cloverInstrDir
391 }
392
393 def getDate(format) {
394   def date = new Date()
395   //return date.format("dd MMMM yyyy")
396   return date.format(format)
397 }
398
399 def getGitHash() {
400   def stdout = new ByteArrayOutputStream()
401   exec {
402     commandLine "git", "rev-parse", "--short", "HEAD"
403     standardOutput = stdout
404     workingDir = jalviewDir
405   }
406   return stdout.toString().trim()
407 }
408
409 def getGitBranch() {
410   def stdout = new ByteArrayOutputStream()
411   exec {
412     commandLine "git", "rev-parse", "--abbrev-ref", "HEAD"
413     standardOutput = stdout
414     workingDir = jalviewDir
415   }
416   return stdout.toString().trim()
417 }
418
419 task createBuildProperties(type: WriteProperties) {
420   inputs.dir("$jalviewDir/$sourceDir")
421   inputs.dir("$jalviewDir/$resourceDir")
422   outputFile "$classes/$buildPropertiesFile"
423   /* taking time/date specific comment out to allow better incremental builds */
424   //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
425   comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
426   property "BUILD_DATE", getDate("dd MMMM yyyy")
427   property "VERSION", JALVIEW_VERSION
428   property "INSTALLATION", INSTALLATION+" git-commit:"+getGitHash()+" ["+getGitBranch()+"]"
429   outputs.file(outputFile)
430   outputs.dir("$classes")
431 }
432
433 task syncDocs(type: Sync) {
434   def syncDir = "$classes/$docDir"
435   from fileTree("$jalviewDir/$docDir")
436   into syncDir
437
438 }
439
440 def helpFile = "$classes/$helpDir/help.jhm"
441 task syncHelp(type: Sync) {
442   inputs.files("$jalviewDir/$helpDir")
443   outputs.files(helpFile)
444
445   def syncDir = "$classes/$helpDir"
446   from fileTree("$jalviewDir/$helpDir")
447   into syncDir
448 }
449
450 task copyHelp(type: Copy) {
451   def inputDir = "$jalviewDir/$helpDir"
452   def outputDir = "$classes/$helpDir"
453   from inputDir
454   into outputDir
455   filter(ReplaceTokens, beginToken: '$$', endToken: '$$', tokens: ['Version-Rel': "USING_FILTER"])
456   inputs.dir(inputDir)
457   outputs.files(helpFile)
458   outputs.dir(outputDir)
459 }
460
461 task syncLib(type: Sync) {
462   def syncDir = "$classes/$libDistDir"
463   from fileTree("$jalviewDir/$libDistDir")
464   into syncDir
465 }
466
467 task syncResources(type: Sync) {
468   from "$jalviewDir/$resourceDir"
469   include "**/*.*"
470   exclude "install4j"
471   into "$classes"
472   preserve {
473     include "**"
474   }
475 }
476
477 task prepare {
478   dependsOn syncResources
479   dependsOn syncDocs
480   dependsOn copyHelp
481 }
482
483
484 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
485 test {
486   dependsOn prepare
487   dependsOn compileJava
488   if (use_clover) {
489     dependsOn cloverInstr
490   }
491
492   print("Running tests " + (use_clover?"WITH":"WITHOUT") + " clover [clover="+use_clover+"]\n") 
493   
494   useTestNG() {
495     includeGroups testngGroups
496     preserveOrder true
497     useDefaultListeners=true
498   }
499   
500   workingDir = jalviewDir
501   //systemProperties 'clover.jar' System.properties.clover.jar
502   sourceCompatibility = compile_source_compatibility
503   targetCompatibility = compile_target_compatibility
504   jvmArgs += additional_compiler_args
505   print ("Setting target compatibility to "+targetCompatibility+"\n")
506 }
507
508 task buildIndices(type: JavaExec) {
509   dependsOn copyHelp
510   classpath = sourceSets.main.compileClasspath
511   main = "com.sun.java.help.search.Indexer"
512   workingDir = "$classes/$helpDir"
513   def argDir = "html"
514   args = [ argDir ]
515   inputs.dir("$workingDir/$argDir")
516
517   outputs.dir("$classes/doc")
518   outputs.dir("$classes/help")
519   outputs.file("$workingDir/JavaHelpSearch/DOCS")
520   outputs.file("$workingDir/JavaHelpSearch/DOCS.TAB")
521   outputs.file("$workingDir/JavaHelpSearch/OFFSETS")
522   outputs.file("$workingDir/JavaHelpSearch/POSITIONS")
523   outputs.file("$workingDir/JavaHelpSearch/SCHEMA")
524   outputs.file("$workingDir/JavaHelpSearch/TMAP")
525 }
526
527 task compileLinkCheck(type: JavaCompile) {
528   options.fork = true
529   classpath = files("$jalviewDir/$utilsDir")
530   destinationDir = file("$jalviewDir/$utilsDir")
531   source = fileTree(dir: "$jalviewDir/$utilsDir", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
532
533   outputs.file("$jalviewDir/$utilsDir/HelpLinksChecker.class")
534   outputs.file("$jalviewDir/$utilsDir/BufferedLineReader.class")
535 }
536
537 def helplinkscheckeroutputfile = file("$jalviewDir/$utilsDir/HelpLinksChecker.out")
538 task linkCheck(type: JavaExec) {
539   dependsOn prepare, compileLinkCheck
540   classpath = files("$jalviewDir/$utilsDir")
541   main = "HelpLinksChecker"
542   workingDir = jalviewDir
543   def help = "$classes/$helpDir"
544   args = [ "$classes/$helpDir", "-nointernet" ]
545   //args = [ "$classesDir/$helpDir", "-nointernet" ]
546
547   doFirst {
548     helplinkscheckeroutputfile.createNewFile()
549     standardOutput new FileOutputStream(helplinkscheckeroutputfile, false)
550   }
551
552   outputs.file(helplinkscheckeroutputfile)
553 }
554
555 task cleanPackageDir(type: Delete) {
556   delete fileTree("$jalviewDir/$packageDir").include("*.jar")
557 }
558
559 jar {
560   dependsOn linkCheck
561   dependsOn buildIndices
562   dependsOn createBuildProperties
563
564   manifest {
565     attributes "Main-Class": mainClass,
566     "Permissions": "all-permissions",
567     "Application-Name": "Jalview Desktop",
568     "Codebase": application_codebase
569   }
570
571   destinationDir = file("$jalviewDir/$packageDir")
572   archiveName = rootProject.name+".jar"
573
574   exclude "cache*/**"
575   exclude "*.jar"
576   exclude "*.jar.*"
577   exclude "**/*.jar"
578   exclude "**/*.jar.*"
579
580   inputs.dir("$classes")
581   outputs.file("$jalviewDir/$packageDir/$archiveName")
582 }
583
584 task copyJars(type: Copy) {
585   from fileTree("$classes").include("**/*.jar").include("*.jar").files
586   into "$jalviewDir/$packageDir"
587 }
588
589 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
590 task syncJars(type: Sync) {
591   from fileTree("$jalviewDir/$libDistDir").include("**/*.jar").include("*.jar").files
592   into "$jalviewDir/$packageDir"
593   preserve {
594     include jar.archiveName
595   }
596 }
597
598 task makeDist {
599   group = "build"
600   description = "Put all required libraries in dist"
601   // order of "cleanPackageDir", "copyJars", "jar" important!
602   jar.mustRunAfter cleanPackageDir
603   syncJars.mustRunAfter cleanPackageDir
604   dependsOn cleanPackageDir
605   dependsOn syncJars
606   dependsOn jar
607   outputs.dir("$jalviewDir/$packageDir")
608 }
609
610 task cleanDist {
611   dependsOn cleanPackageDir
612   dependsOn cleanTest
613   dependsOn clean
614 }
615
616 shadowJar {
617   dependsOn makeDist
618   from ("$jalviewDir/$libDistDir") {
619       include("*.jar")
620   }
621   mainClassName = shadowJarMainClass
622   mergeServiceFiles()
623   classifier = "all-"+JAVA_VERSION
624   minimize()
625 }
626
627 task getdownWebsite() {
628   group = "distribution"
629   description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
630   dependsOn makeDist
631   def getdownWebsiteResourceFilenames = []
632   def getdownTextString = ""
633   def getdownResourceDir = project.ext.getdownResourceDir
634   def getdownAppDir = project.ext.getdownAppDir
635   def getdownResourceFilenames = []
636   doFirst {
637     // go through properties looking for getdown_txt_...
638     def props = project.properties.sort { it.key }
639     props.put("getdown_txt_java_min_version", getdown_alt_java_min_version)
640     props.put("getdown_txt_multi_java_location", getdown_alt_multi_java_location)
641     
642     props.put("getdown_txt_appbase", getdown_app_base)
643     props.each{ prop, val ->
644       if (prop.startsWith("getdown_txt_") && val != null) {
645         if (prop.startsWith("getdown_txt_multi_")) {
646           def key = prop.substring(18)
647           val.split(",").each{ v ->
648             def line = key + " = " + v + "\n"
649             getdownTextString += line
650           }
651         } else {
652           // file values rationalised
653           if (val.indexOf('/') > -1) {
654             def r = null
655             if (val.indexOf('/') == 0) {
656               // absolute path
657               r = file(val)
658             } else if (val.indexOf('/') > 0) {
659               // relative path (relative to jalviewDir)
660               r = file( jalviewDir + '/' + val )
661             }
662             if (r.exists()) {
663               val = getdown_resource_dir + '/' + r.getName()
664               getdownWebsiteResourceFilenames += val
665               getdownResourceFilenames += r.getPath()
666             }
667           }
668           def line = prop.substring(12) + " = " + val + "\n"
669           getdownTextString += line
670         }
671       }
672     }
673
674     getdownWebsiteResourceFilenames.each{ filename ->
675       getdownTextString += "resource = "+filename+"\n"
676     }
677     getdownResourceFilenames.each{ filename ->
678       copy {
679         from filename
680         into project.ext.getdownResourceDir
681       }
682     }
683
684     def codeFiles = []
685     makeDist.outputs.files.each{ f ->
686       if (f.isDirectory()) {
687         def files = fileTree(dir: f, include: ["*"]).getFiles()
688         codeFiles += files
689       } else if (f.exists()) {
690         codeFiles += f
691       }
692     }
693     codeFiles.sort().each{f ->
694       def line = "code = " + getdown_app_dir + '/' + f.getName() + "\n"
695       getdownTextString += line
696       copy {
697         from f.getPath()
698         into project.ext.getdownAppDir
699       }
700     }
701
702     if (JAVA_VERSION.equals("11")) {
703       def j11libFiles = fileTree(dir: "$jalviewDir/$j11libDir", include: ["*.jar"]).getFiles()
704       j11libFiles.sort().each{f ->
705         def line = "code = " + getdown_j11lib_dir + '/' + f.getName() + "\n"
706         getdownTextString += line
707         copy {
708           from f.getPath()
709           into project.ext.getdownJ11libDir
710         }
711       }
712     }
713
714     getdownTextString += "code = " + file(getdownLauncher).getName() + "\n"
715     getdownTextString += "class = " + mainClass + "\n"
716
717     def getdown_txt = file(project.ext.getdownWebsiteDir + "/getdown.txt")
718     getdown_txt.write(getdownTextString)
719
720     copy {
721       from getdown_txt
722       into project.ext.getdownFilesDir
723     }
724
725     copy {
726       from getdownLauncher
727       into project.ext.getdownWebsiteDir
728     }
729
730     copy {
731       from getdownLauncher
732       into project.ext.getdownFilesDir
733     }
734
735     copy {
736       from getdownLib1
737       into project.ext.getdownFilesDir
738     }
739
740     copy {
741       from getdownLib1
742       into project.ext.getdownWebsiteDir
743     }
744
745     copy {
746       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.background_image')
747       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.error_background')
748       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.progress_image')
749       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.icon')
750       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.mac_dock_icon')
751       into project.ext.getdownFilesDir + '/' + getdown_resource_dir 
752     }
753   }
754
755   inputs.dir(jalviewDir + '/' + packageDir)
756   outputs.dir(project.ext.getdownWebsiteDir)
757   outputs.dir(project.ext.getdownFilesDir)
758 }
759
760 task getdownDigest(type: JavaExec) {
761   group = "distribution"
762   description = "Digest the getdown website folder"
763   dependsOn getdownWebsite
764   classpath = files(jalviewDir + '/' + getdown_core)
765   classpath file(jalviewDir + '/' + getdown_lib1)
766   main = "com.threerings.getdown.tools.Digester"
767   args project.ext.getdownWebsiteDir
768   outputs.file(project.ext.getdownWebsiteDir + '/' + "digest2.txt")
769 }
770
771 task getdown() {
772   group = "distribution"
773   description = "Create the minimal and full getdown app folder for installers and website and create digest file"
774   dependsOn getdownDigest
775 }
776
777 clean {
778   delete project.ext.getdownWebsiteDir
779   delete project.ext.getdownFilesDir
780 }
781
782 install4j {
783   def install4jHomeDir = "/opt/install4j"
784   def hostname = "hostname".execute().text.trim()
785   if (hostname.equals("jv-bamboo")) {
786     install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
787   } else if (OperatingSystem.current().isMacOsX()) {
788     install4jHomeDir = '/Applications/install4j.app/Contents/Resources/app'
789     if (! file(install4jHomeDir).exists()) {
790       install4jHomeDir = System.getProperty("user.home")+install4jHomeDir
791     }
792   } else if (OperatingSystem.current().isLinux()) {
793     install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
794   }
795   installDir = file(install4jHomeDir)
796   mediaTypes = Arrays.asList(install4jMediaTypes.split(","))
797 }
798
799 def install4jConf
800 def macosJavaVMDir
801 def windowsJavaVMDir
802 def install4jDir = "$jalviewDir/$install4jResourceDir"
803 def install4jConfFile = "jalview-installers-java"+JAVA_VERSION+".install4j"
804 install4jConf = "$install4jDir/$install4jConfFile"
805   
806 task copyInstall4jTemplate(type: Copy) {
807   macosJavaVMDir = System.env.HOME+"/buildtools/jre/openjdk-java_vm/macos-jre"+JAVA_VERSION+"/java_vm"
808   windowsJavaVMDir = System.env.HOME+"/buildtools/jre/openjdk-java_vm/windows-jre"+JAVA_VERSION+"/java_vm"
809   from (install4jDir) {
810     include install4jTemplate
811     rename (install4jTemplate, install4jConfFile)
812     filter(ReplaceTokens, beginToken: '', endToken: '', tokens: ['9999999999': JAVA_VERSION])
813     filter(ReplaceTokens, beginToken: '$$', endToken: '$$', tokens: ['VERSION': JALVIEW_VERSION, 'MACOS_JAVA_VM_DIR': macosJavaVMDir, 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir])
814   }
815   into install4jDir
816   inputs.files("$install4jDir/$install4jTemplate")
817   outputs.files(install4jConf)
818 }
819
820 task installers(type: com.install4j.gradle.Install4jTask) {
821   group = "distribution"
822   description = "Create the install4j installers"
823   dependsOn getdown
824   dependsOn copyInstall4jTemplate
825   projectFile = file(install4jConf)
826   println("Using projectFile "+projectFile)
827   variables = [majorVersion: version.substring(2, 11), build: 001]
828   destination = "$jalviewDir/$install4jBuildDir/$JAVA_VERSION"
829   buildSelected = true
830   inputs.dir(project.ext.getdownWebsiteDir)
831   inputs.file(install4jConf)
832   inputs.dir(macosJavaVMDir)
833   inputs.dir(windowsJavaVMDir)
834   outputs.dir("$jalviewDir/$install4jBuildDir/$JAVA_VERSION")
835 }
836
837 clean {
838   delete install4jConf
839 }