ed3ace3a3c3238f6b19219677608cecc2f3b889b
[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" || entry.path == "resources")) {
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         HashMap<String, Boolean> addedLibPath = new HashMap<>();
236         def allPaths = sourceSets.test.compileClasspath + sourceSets.main.compileClasspath
237         sourceSets.main.compileClasspath.each{
238           //if ((it.isDirectory() || ! it.exists()) && ! (it.equals(sourceSets.main.java.outputDir))) {
239           //no longer want to add outputDir as eclipse is using its own output dir in bin/main
240           if (it.isDirectory() || ! it.exists()) {
241             // don't add dirs to classpath
242             //println("Not adding directory "+it)
243             return
244           }
245           def itPath = it.toString()
246           if (itPath.startsWith(jalviewDirAbsolutePath+"/")) {
247             itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
248           }
249           if (addedLibPath.get(itPath)) {
250             //println("Not adding duplicate entry "+itPath)
251           } else {
252             //println("Adding entry "+itPath)
253             node.appendNode('classpathentry', [kind:"lib", path:itPath])
254             addedLibPath.put(itPath, true)
255           }
256         }
257         sourceSets.test.compileClasspath.each{
258           //if ((it.isDirectory() || ! it.exists()) && ! (it.equals(sourceSets.main.java.outputDir))) {
259           //no longer want to add outputDir as eclipse is using its own output dir in bin/main
260           if (it.isDirectory() || ! it.exists()) {
261             // don't add dirs to classpath
262             //println("Not adding directory "+it)
263             return
264           }
265           def itPath = it.toString()
266           if (itPath.startsWith(jalviewDirAbsolutePath+"/")) {
267             itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
268           }
269           if (addedLibPath.get(itPath)) {
270             //println("Not adding duplicate entry "+itPath)
271           } else {
272             //println("Adding entry "+itPath)
273             node.appendNode('classpathentry', [kind:"lib", path:itPath])
274               .appendNode('attributes')
275                 .appendNode('attribute', [name:"test", value:"true"])
276             addedLibPath.put(itPath, true)
277           }
278         }
279       }
280
281     }
282   }
283
284   jdt {
285     // for the IDE, use java 11 compatibility
286     sourceCompatibility = 11
287     targetCompatibility = 11
288     javaRuntimeName = "JavaSE-11"
289
290     file {
291       withProperties { props ->
292         def jalview_prefs = new Properties()
293                 def ins = new FileInputStream(eclipse_extra_jdt_prefs_file)
294                 jalview_prefs.load(ins)
295                 ins.close()
296                 jalview_prefs.forEach { t, v ->
297                         if (props.getAt(t) == null) {
298                                 props.putAt(t, v)
299                         }
300                 }
301       }
302     }
303   }
304
305 }
306
307 task cloverInstr() {
308   // only instrument source, we build test classes as normal
309     inputs.files files (sourceSets.main.allJava) // , fileTree(dir:"$jalviewDir/$testSourceDir", include: ["**/*.java"]))
310     outputs.dir cloverInstrDir
311
312     doFirst {
313         delete cloverInstrDir
314         def argsList = ["--initstring", "${buildDir}/clover/clover.db",
315                         "-d", "${buildDir}/${cloverSourcesInstrDir}"]
316         argsList.addAll(inputs.files.files.collect({ file ->
317             file.absolutePath
318         }))
319         String[] args = argsList.toArray()
320         println("About to instrument "+args.length +" files")
321         com.atlassian.clover.CloverInstr.mainImpl(args)
322     }
323 }
324
325  
326 task cloverReport {
327         group = "Verification"
328         description = "Createst the Clover report"
329     inputs.dir "${buildDir}/clover"
330     outputs.dir "${reportsDir}/clover"
331     onlyIf {
332         file("${buildDir}/clover/clover.db").exists()
333     }
334     doFirst {
335         def argsList = ["--initstring", "${buildDir}/clover/clover.db",
336                         "-o", "${reportsDir}/clover"]
337         String[] args = argsList.toArray()
338         com.atlassian.clover.reporters.html.HtmlReporter.runReport(args)
339         
340         // and generate ${reportsDir}/clover/clover.xml
341         args = ["--initstring", "${buildDir}/clover/clover.db",
342                         "-o", "${reportsDir}/clover/clover.xml"].toArray()
343         com.atlassian.clover.reporters.xml.XMLReporter.runReport(args)
344     }
345 }
346
347 // end clover bits
348
349
350 compileJava {
351
352   doFirst {
353     sourceCompatibility = compile_source_compatibility
354     targetCompatibility = compile_target_compatibility
355     options.compilerArgs = additional_compiler_args
356     print ("Setting target compatibility to "+targetCompatibility+"\n")
357   }
358
359 }
360
361 compileTestJava {
362   if (use_clover) {
363     dependsOn compileCloverJava
364     classpath += configurations.cloverRuntime
365   } else {
366     classpath += sourceSets.main.runtimeClasspath
367   }
368   doFirst {
369     sourceCompatibility = compile_source_compatibility
370     targetCompatibility = compile_target_compatibility
371     options.compilerArgs = additional_compiler_args
372     print ("Setting target compatibility to "+targetCompatibility+"\n")
373   }
374 }
375
376
377 compileCloverJava {
378
379   doFirst {
380     sourceCompatibility = compile_source_compatibility
381     targetCompatibility = compile_target_compatibility
382     options.compilerArgs += additional_compiler_args
383     print ("Setting target compatibility to "+targetCompatibility+"\n")
384   }
385   classpath += configurations.cloverRuntime
386 }
387
388 clean {
389   delete sourceSets.main.java.outputDir
390 }
391
392 cleanTest {
393   delete sourceSets.test.java.outputDir
394   delete cloverInstrDir
395 }
396
397 def getDate(format) {
398   def date = new Date()
399   //return date.format("dd MMMM yyyy")
400   return date.format(format)
401 }
402
403 def getGitHash() {
404   def stdout = new ByteArrayOutputStream()
405   exec {
406     commandLine "git", "rev-parse", "--short", "HEAD"
407     standardOutput = stdout
408     workingDir = jalviewDir
409   }
410   return stdout.toString().trim()
411 }
412
413 def getGitBranch() {
414   def stdout = new ByteArrayOutputStream()
415   exec {
416     commandLine "git", "rev-parse", "--abbrev-ref", "HEAD"
417     standardOutput = stdout
418     workingDir = jalviewDir
419   }
420   return stdout.toString().trim()
421 }
422
423 task createBuildProperties(type: WriteProperties) {
424   inputs.dir("$jalviewDir/$sourceDir")
425   inputs.dir("$jalviewDir/$resourceDir")
426   outputFile "$classes/$buildPropertiesFile"
427   /* taking time/date specific comment out to allow better incremental builds */
428   //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
429   comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
430   property "BUILD_DATE", getDate("dd MMMM yyyy")
431   property "VERSION", JALVIEW_VERSION
432   property "INSTALLATION", INSTALLATION+" git-commit:"+getGitHash()+" ["+getGitBranch()+"]"
433   outputs.file(outputFile)
434   outputs.dir("$classes")
435 }
436
437 task syncDocs(type: Sync) {
438   def syncDir = "$classes/$docDir"
439   from fileTree("$jalviewDir/$docDir")
440   into syncDir
441
442 }
443
444 def helpFile = "$classes/$helpDir/help.jhm"
445 task syncHelp(type: Sync) {
446   inputs.files("$jalviewDir/$helpDir")
447   outputs.files(helpFile)
448
449   def syncDir = "$classes/$helpDir"
450   from fileTree("$jalviewDir/$helpDir")
451   into syncDir
452 }
453
454 task copyHelp(type: Copy) {
455   def inputDir = "$jalviewDir/$helpDir"
456   def outputDir = "$classes/$helpDir"
457   from inputDir
458   into outputDir
459   filter(ReplaceTokens, beginToken: '$$', endToken: '$$', tokens: ['Version-Rel': "USING_FILTER"])
460   inputs.dir(inputDir)
461   outputs.files(helpFile)
462   outputs.dir(outputDir)
463 }
464
465 task syncLib(type: Sync) {
466   def syncDir = "$classes/$libDistDir"
467   from fileTree("$jalviewDir/$libDistDir")
468   into syncDir
469 }
470
471 task syncResources(type: Sync) {
472   from "$jalviewDir/$resourceDir"
473   include "**/*.*"
474   exclude "install4j"
475   into "$classes"
476   preserve {
477     include "**"
478   }
479 }
480
481 task prepare {
482   dependsOn syncResources
483   dependsOn syncDocs
484   dependsOn copyHelp
485 }
486
487
488 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
489 test {
490   dependsOn prepare
491   dependsOn compileJava
492   if (use_clover) {
493     dependsOn cloverInstr
494   }
495
496   print("Running tests " + (use_clover?"WITH":"WITHOUT") + " clover [clover="+use_clover+"]\n") 
497   
498   useTestNG() {
499     includeGroups testngGroups
500     preserveOrder true
501     useDefaultListeners=true
502   }
503   
504   workingDir = jalviewDir
505   //systemProperties 'clover.jar' System.properties.clover.jar
506   sourceCompatibility = compile_source_compatibility
507   targetCompatibility = compile_target_compatibility
508   jvmArgs += additional_compiler_args
509   print ("Setting target compatibility to "+targetCompatibility+"\n")
510 }
511
512 task buildIndices(type: JavaExec) {
513   dependsOn copyHelp
514   classpath = sourceSets.main.compileClasspath
515   main = "com.sun.java.help.search.Indexer"
516   workingDir = "$classes/$helpDir"
517   def argDir = "html"
518   args = [ argDir ]
519   inputs.dir("$workingDir/$argDir")
520
521   outputs.dir("$classes/doc")
522   outputs.dir("$classes/help")
523   outputs.file("$workingDir/JavaHelpSearch/DOCS")
524   outputs.file("$workingDir/JavaHelpSearch/DOCS.TAB")
525   outputs.file("$workingDir/JavaHelpSearch/OFFSETS")
526   outputs.file("$workingDir/JavaHelpSearch/POSITIONS")
527   outputs.file("$workingDir/JavaHelpSearch/SCHEMA")
528   outputs.file("$workingDir/JavaHelpSearch/TMAP")
529 }
530
531 task compileLinkCheck(type: JavaCompile) {
532   options.fork = true
533   classpath = files("$jalviewDir/$utilsDir")
534   destinationDir = file("$jalviewDir/$utilsDir")
535   source = fileTree(dir: "$jalviewDir/$utilsDir", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
536
537   outputs.file("$jalviewDir/$utilsDir/HelpLinksChecker.class")
538   outputs.file("$jalviewDir/$utilsDir/BufferedLineReader.class")
539 }
540
541 def helplinkscheckeroutputfile = file("$jalviewDir/$utilsDir/HelpLinksChecker.out")
542 task linkCheck(type: JavaExec) {
543   dependsOn prepare, compileLinkCheck
544   classpath = files("$jalviewDir/$utilsDir")
545   main = "HelpLinksChecker"
546   workingDir = jalviewDir
547   def help = "$classes/$helpDir"
548   args = [ "$classes/$helpDir", "-nointernet" ]
549   //args = [ "$classesDir/$helpDir", "-nointernet" ]
550
551   doFirst {
552     helplinkscheckeroutputfile.createNewFile()
553     standardOutput new FileOutputStream(helplinkscheckeroutputfile, false)
554   }
555
556   outputs.file(helplinkscheckeroutputfile)
557 }
558
559 task cleanPackageDir(type: Delete) {
560   delete fileTree("$jalviewDir/$packageDir").include("*.jar")
561 }
562
563 jar {
564   dependsOn linkCheck
565   dependsOn buildIndices
566   dependsOn createBuildProperties
567
568   manifest {
569     attributes "Main-Class": mainClass,
570     "Permissions": "all-permissions",
571     "Application-Name": "Jalview Desktop",
572     "Codebase": application_codebase
573   }
574
575   destinationDir = file("$jalviewDir/$packageDir")
576   archiveName = rootProject.name+".jar"
577
578   exclude "cache*/**"
579   exclude "*.jar"
580   exclude "*.jar.*"
581   exclude "**/*.jar"
582   exclude "**/*.jar.*"
583
584   inputs.dir("$classes")
585   outputs.file("$jalviewDir/$packageDir/$archiveName")
586 }
587
588 task copyJars(type: Copy) {
589   from fileTree("$classes").include("**/*.jar").include("*.jar").files
590   into "$jalviewDir/$packageDir"
591 }
592
593 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
594 task syncJars(type: Sync) {
595   from fileTree("$jalviewDir/$libDistDir").include("**/*.jar").include("*.jar").files
596   into "$jalviewDir/$packageDir"
597   preserve {
598     include jar.archiveName
599   }
600 }
601
602 task makeDist {
603   group = "build"
604   description = "Put all required libraries in dist"
605   // order of "cleanPackageDir", "copyJars", "jar" important!
606   jar.mustRunAfter cleanPackageDir
607   syncJars.mustRunAfter cleanPackageDir
608   dependsOn cleanPackageDir
609   dependsOn syncJars
610   dependsOn jar
611   outputs.dir("$jalviewDir/$packageDir")
612 }
613
614 task cleanDist {
615   dependsOn cleanPackageDir
616   dependsOn cleanTest
617   dependsOn clean
618 }
619
620 shadowJar {
621   dependsOn makeDist
622   from ("$jalviewDir/$libDistDir") {
623       include("*.jar")
624   }
625   mainClassName = shadowJarMainClass
626   mergeServiceFiles()
627   classifier = "all-"+JAVA_VERSION
628   minimize()
629 }
630
631 task getdownWebsite() {
632   group = "distribution"
633   description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
634   dependsOn makeDist
635   def getdownWebsiteResourceFilenames = []
636   def getdownTextString = ""
637   def getdownResourceDir = project.ext.getdownResourceDir
638   def getdownAppDir = project.ext.getdownAppDir
639   def getdownResourceFilenames = []
640   doFirst {
641     // go through properties looking for getdown_txt_...
642     def props = project.properties.sort { it.key }
643     props.put("getdown_txt_java_min_version", getdown_alt_java_min_version)
644     props.put("getdown_txt_multi_java_location", getdown_alt_multi_java_location)
645     
646     props.put("getdown_txt_appbase", getdown_app_base)
647     props.each{ prop, val ->
648       if (prop.startsWith("getdown_txt_") && val != null) {
649         if (prop.startsWith("getdown_txt_multi_")) {
650           def key = prop.substring(18)
651           val.split(",").each{ v ->
652             def line = key + " = " + v + "\n"
653             getdownTextString += line
654           }
655         } else {
656           // file values rationalised
657           if (val.indexOf('/') > -1) {
658             def r = null
659             if (val.indexOf('/') == 0) {
660               // absolute path
661               r = file(val)
662             } else if (val.indexOf('/') > 0) {
663               // relative path (relative to jalviewDir)
664               r = file( jalviewDir + '/' + val )
665             }
666             if (r.exists()) {
667               val = getdown_resource_dir + '/' + r.getName()
668               getdownWebsiteResourceFilenames += val
669               getdownResourceFilenames += r.getPath()
670             }
671           }
672           def line = prop.substring(12) + " = " + val + "\n"
673           getdownTextString += line
674         }
675       }
676     }
677
678     getdownWebsiteResourceFilenames.each{ filename ->
679       getdownTextString += "resource = "+filename+"\n"
680     }
681     getdownResourceFilenames.each{ filename ->
682       copy {
683         from filename
684         into project.ext.getdownResourceDir
685       }
686     }
687
688     def codeFiles = []
689     makeDist.outputs.files.each{ f ->
690       if (f.isDirectory()) {
691         def files = fileTree(dir: f, include: ["*"]).getFiles()
692         codeFiles += files
693       } else if (f.exists()) {
694         codeFiles += f
695       }
696     }
697     codeFiles.sort().each{f ->
698       def line = "code = " + getdown_app_dir + '/' + f.getName() + "\n"
699       getdownTextString += line
700       copy {
701         from f.getPath()
702         into project.ext.getdownAppDir
703       }
704     }
705
706     // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
707     /*
708     if (JAVA_VERSION.equals("11")) {
709       def j11libFiles = fileTree(dir: "$jalviewDir/$j11libDir", include: ["*.jar"]).getFiles()
710       j11libFiles.sort().each{f ->
711         def line = "code = " + getdown_j11lib_dir + '/' + f.getName() + "\n"
712         getdownTextString += line
713         copy {
714           from f.getPath()
715           into project.ext.getdownJ11libDir
716         }
717       }
718     }
719     */
720
721     getdownTextString += "code = " + file(getdownLauncher).getName() + "\n"
722     getdownTextString += "class = " + mainClass + "\n"
723
724     def getdown_txt = file(project.ext.getdownWebsiteDir + "/getdown.txt")
725     getdown_txt.write(getdownTextString)
726
727     copy {
728       from getdown_txt
729       into project.ext.getdownFilesDir
730     }
731
732     copy {
733       from getdownLauncher
734       into project.ext.getdownFilesDir
735     }
736
737     copy {
738       from getdownLauncher
739       into project.ext.getdownWebsiteDir
740     }
741
742     copy {
743       from getdownLib1
744       into project.ext.getdownFilesDir + '/' + packageDir
745     }
746
747     copy {
748       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.background_image')
749       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.error_background')
750       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.progress_image')
751       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.icon')
752       from jalviewDir + '/' + project.getProperty('getdown_txt_ui.mac_dock_icon')
753       into project.ext.getdownFilesDir + '/' + getdown_resource_dir 
754     }
755   }
756
757   inputs.dir(jalviewDir + '/' + packageDir)
758   outputs.dir(project.ext.getdownWebsiteDir)
759   outputs.dir(project.ext.getdownFilesDir)
760 }
761
762 task getdownDigest(type: JavaExec) {
763   group = "distribution"
764   description = "Digest the getdown website folder"
765   dependsOn getdownWebsite
766   classpath = files(jalviewDir + '/' + getdown_core)
767   classpath file(jalviewDir + '/' + getdown_lib1)
768   main = "com.threerings.getdown.tools.Digester"
769   args project.ext.getdownWebsiteDir
770   outputs.file(project.ext.getdownWebsiteDir + '/' + "digest2.txt")
771 }
772
773 task getdown() {
774   group = "distribution"
775   description = "Create the minimal and full getdown app folder for installers and website and create digest file"
776   dependsOn getdownDigest
777 }
778
779 clean {
780   delete project.ext.getdownWebsiteDir
781   delete project.ext.getdownFilesDir
782 }
783
784 install4j {
785   def install4jHomeDir = "/opt/install4j"
786   def hostname = "hostname".execute().text.trim()
787   if (hostname.equals("jv-bamboo")) {
788     install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
789   } else if (OperatingSystem.current().isMacOsX()) {
790     install4jHomeDir = '/Applications/install4j.app/Contents/Resources/app'
791     if (! file(install4jHomeDir).exists()) {
792       install4jHomeDir = System.getProperty("user.home")+install4jHomeDir
793     }
794   } else if (OperatingSystem.current().isLinux()) {
795     install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
796   }
797   installDir = file(install4jHomeDir)
798   mediaTypes = Arrays.asList(install4jMediaTypes.split(","))
799 }
800
801 def install4jConf
802 def macosJavaVMDir
803 def macosJavaVMTgz
804 def windowsJavaVMDir
805 def windowsJavaVMTgz
806 def install4jDir = "$jalviewDir/$install4jResourceDir"
807 def install4jConfFile = "jalview-installers-java"+JAVA_VERSION+".install4j"
808 install4jConf = "$install4jDir/$install4jConfFile"
809   
810 task copyInstall4jTemplate(type: Copy) {
811   macosJavaVMDir = System.env.HOME+"/buildtools/jre/openjdk-java_vm/getdown/macos-jre"+JAVA_VERSION+"/jre"
812   macosJavaVMTgz = System.env.HOME+"/buildtools/jre/openjdk-java_vm/install4j/tgz/macos-jre"+JAVA_VERSION+".tar.gz"
813   windowsJavaVMDir = System.env.HOME+"/buildtools/jre/openjdk-java_vm/getdown/windows-jre"+JAVA_VERSION+"/jre"
814   windowsJavaVMTgz = System.env.HOME+"/buildtools/jre/openjdk-java_vm/install4j/tgz/windows-jre"+JAVA_VERSION+".tar.gz"
815   from (install4jDir) {
816     include install4jTemplate
817     rename (install4jTemplate, install4jConfFile)
818     filter(ReplaceTokens, beginToken: '', endToken: '', tokens: ['9999999999': JAVA_VERSION])
819     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])
820   }
821   into install4jDir
822   inputs.files("$install4jDir/$install4jTemplate")
823   outputs.files(install4jConf)
824 }
825
826 task installers(type: com.install4j.gradle.Install4jTask) {
827   group = "distribution"
828   description = "Create the install4j installers"
829   dependsOn getdown
830   dependsOn copyInstall4jTemplate
831   projectFile = file(install4jConf)
832   println("Using projectFile "+projectFile)
833   variables = [majorVersion: version.substring(2, 11), build: 001]
834   destination = "$jalviewDir/$install4jBuildDir/$JAVA_VERSION"
835   buildSelected = true
836   inputs.dir(project.ext.getdownWebsiteDir)
837   inputs.file(install4jConf)
838   inputs.dir(macosJavaVMDir)
839   inputs.dir(windowsJavaVMDir)
840   outputs.dir("$jalviewDir/$install4jBuildDir/$JAVA_VERSION")
841 }
842
843 clean {
844   delete install4jConf
845 }