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