ed026ef567871ccf64fecd6977e3c00fdea20152
[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
6 import groovy.transform.ExternalizeMethods
7
8 buildscript {
9   dependencies {
10     classpath 'org.openclover:clover:4.3.1'
11   }
12 }
13
14 plugins {
15   id 'java'
16   id 'application'
17   id 'eclipse'
18   id 'com.github.johnrengelman.shadow' version '4.0.3'
19   id 'com.install4j.gradle' version '7.0.9'
20   id 'com.dorongold.task-tree' version '1.4' // only needed to display task dependency tree with  gradle task1 [task2 ...] taskTree
21 }
22
23 repositories {
24   jcenter()
25   mavenCentral()
26   mavenLocal()
27   flatDir {
28     dirs gradlePluginsDir
29   }
30 }
31
32 dependencies {
33   compile 'org.apache.commons:commons-compress:1.18'
34 }
35
36
37 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
38 def string(Object o) {
39   return o.toString()
40 }
41
42
43 ext {
44   jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
45
46   // local build environment properties
47   def localProps = "${jalviewDirAbsolutePath}/local.properties"
48   if (file(localProps).exists()) {
49     try {
50       def p = new Properties()
51       def localPropsFIS = new FileInputStream(localProps)
52       p.load(localPropsFIS)
53       localPropsFIS.close()
54       p.each {
55         key, val -> 
56           def over = getProperty(key) != null
57           setProperty(key, val)
58           if (over) {
59             println("Overriding property '${key}' with local.properties value '${val}'")
60           }
61       }
62     } catch (Exception e) {
63       System.out.println("Exception reading local.properties")
64     }
65   }
66
67
68   // this property set when running Eclipse headlessly
69   j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
70   // this property set by Eclipse
71   eclipseApplicationProperty = string("eclipse.application")
72   // CHECK IF IN ECLIPSE
73   IN_ECLIPSE = System.properties[eclipseApplicationProperty].startsWith("org.eclipse.ui.")
74   if (System.properties[j2sHeadlessBuildProperty].equals("true")) { // headless build property has been set
75     println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
76     IN_ECLIPSE = false
77   }
78   /*
79   System.properties.sort { it.key }.each {
80     key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
81   }
82   */
83
84   mainClassName = string(launcherClass)
85
86   cloverInstrDir = file("${buildDir}/${cloverSourcesInstrDir}")
87   classes = string("${jalviewDir}/${classesDir}")
88   if (clover.equals("true")) {
89     use_clover = true
90     classes = string("${buildDir}/${cloverClassesDir}")
91   } else {
92     use_clover = false
93     classes = string("${jalviewDir}/${classesDir}")
94   }
95
96   getdownWebsiteDir = string("${jalviewDir}/${getdown_website_dir}/${JAVA_VERSION}")
97   getdownDir = string("")
98   reportRsyncCmd = false
99   buildDist = true
100   buildProperties = build_properties_file
101   getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
102   switch (CHANNEL) {
103
104     case "BUILD":
105     // TODO: get bamboo build artifact URL for getdown artifacts
106     getdown_channel_base = bamboo_channelbase
107     getdown_channel_name = string("${bamboo_planKey}/${JAVA_VERSION}")
108     getdown_app_base = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
109     getdown_app_dir = getdown_app_dir_alt
110     buildProperties = string("${jalviewDir}/${classesDir}/${build_properties_file}")
111     break
112
113     case "RELEASE":
114     getdown_channel_name = CHANNEL.toLowerCase()
115     getdownDir = string("${getdown_channel_name}/${JAVA_VERSION}")
116     getdown_app_base = string("${getdown_channel_base}/${getdownDir}")
117     getdown_app_dir = getdown_app_dir_release
118     buildProperties = string("${jalviewDir}/${classesDir}/${build_properties_file}")
119     reportRsyncCommand = true
120     break
121
122     case "ARCHIVE":
123     getdown_channel_name = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
124     getdownDir = string("${getdown_channel_name}/${JAVA_VERSION}")
125     getdown_app_base = string("${getdown_channel_base}/${getdownDir}")
126     getdown_app_dir = getdown_app_dir_alt
127     if (!file("${ARCHIVEDIR}/${packageDir}").exists()) {
128       print "Must provide an ARCHIVEDIR value to produce an archive distribution"
129       exit
130     } else {
131       packageDir = string("${ARCHIVEDIR}/${packageDir}")
132       buildProperties = string("${ARCHIVEDIR}/${classesDir}/${build_properties_file}")
133       buildDist = false
134     }
135     reportRsyncCommand = true
136     break
137
138     case "ARCHIVELOCAL":
139     getdown_channel_name = string("archive/${JALVIEW_VERSION}")
140     getdownDir = string("${getdown_channel_name}/${JAVA_VERSION}")
141     getdown_app_base = file(getdownWebsiteDir).toURI().toString()
142     getdown_app_dir = getdown_app_dir_alt
143     if (!file("${ARCHIVEDIR}/${packageDir}").exists()) {
144       print "Must provide an ARCHIVEDIR value to produce an archive distribution"
145       exit
146     } else {
147       packageDir = string("${ARCHIVEDIR}/${packageDir}")
148       buildProperties = string("${ARCHIVEDIR}/${classesDir}/${build_properties_file}")
149       buildDist = false
150     }
151     reportRsyncCommand = true
152     getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
153     break
154
155     case "DEVELOP":
156     getdown_channel_name = CHANNEL.toLowerCase()
157     getdownDir = string("${getdown_channel_name}/${JAVA_VERSION}")
158     getdown_app_base = string("${getdown_channel_base}/${getdownDir}")
159     getdown_app_dir = getdown_app_dir_alt
160     buildProperties = string("${jalviewDir}/${classesDir}/${build_properties_file}")
161     reportRsyncCommand = true
162     break
163
164     case "TEST-RELEASE":
165     getdown_channel_name = CHANNEL.toLowerCase()
166     getdownDir = string("${getdown_channel_name}/${JAVA_VERSION}")
167     getdown_app_base = string("${getdown_channel_base}/${getdownDir}")
168     getdown_app_dir = getdown_app_dir_alt
169     buildProperties = string("${jalviewDir}/${classesDir}/${build_properties_file}")
170     reportRsyncCommand = true
171     break
172
173     case ~/^SCRATCH(|-[-\w]*)$/:
174     getdown_channel_name = CHANNEL
175     getdownDir = string("${getdown_channel_name}/${JAVA_VERSION}")
176     getdown_app_base = string("${getdown_channel_base}/${getdownDir}")
177     getdown_app_dir = getdown_app_dir_alt
178     buildProperties = string("${jalviewDir}/${classesDir}/${build_properties_file}")
179     reportRsyncCommand = true
180     break
181
182     case "LOCAL":
183     getdown_app_base = file(getdownWebsiteDir).toURI().toString()
184     getdown_app_dir = getdown_app_dir_alt
185     buildProperties = string("${jalviewDir}/${classesDir}/${build_properties_file}")
186     getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
187     break
188
189     default: // something wrong specified
190     print("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
191     exit
192     break
193
194   }
195
196   getdownAppDir = string("${getdownWebsiteDir}/${getdown_app_dir}")
197   //getdownJ11libDir = "${getdownWebsiteDir}/${getdown_j11lib_dir}"
198   getdownResourceDir = string("${getdownWebsiteDir}/${getdown_resource_dir}")
199   getdownInstallDir = string("${getdownWebsiteDir}/${getdown_install_dir}")
200   getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
201   getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
202   /* compile without modules -- using classpath libraries
203   modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
204   modules_runtimeClasspath = modules_compileClasspath
205   */
206   gitHash = string("")
207   gitBranch = string("")
208
209   println("Using a ${CHANNEL} profile.")
210
211   additional_compiler_args = []
212   // configure classpath/args for j8/j11 compilation
213   if (JAVA_VERSION.equals("1.8")) {
214     JAVA_INTEGER_VERSION = string("8")
215     //libDir = j8libDir
216     libDir = j11libDir
217     libDistDir = j8libDir
218     compile_source_compatibility = 1.8
219     compile_target_compatibility = 1.8
220     // these are getdown.txt properties defined dependent on the JAVA_VERSION
221     getdown_alt_java_min_version = getdown_alt_java8_min_version
222     getdown_alt_java_max_version = getdown_alt_java8_max_version
223     // this property is assigned below and expanded to multiple lines in the getdown task
224     getdown_alt_multi_java_location = getdown_alt_java8_txt_multi_java_location
225     // this property is for the Java library used in eclipse
226     eclipse_java_runtime_name = string("JavaSE-1.8")
227   } else if (JAVA_VERSION.equals("11")) {
228     JAVA_INTEGER_VERSION = string("11")
229     libDir = j11libDir
230     libDistDir = j11libDir
231     compile_source_compatibility = 11
232     compile_target_compatibility = 11
233     getdown_alt_java_min_version = getdown_alt_java11_min_version
234     getdown_alt_java_max_version = getdown_alt_java11_max_version
235     getdown_alt_multi_java_location = getdown_alt_java11_txt_multi_java_location
236     eclipse_java_runtime_name = string("JavaSE-11")
237     /* compile without modules -- using classpath libraries
238     additional_compiler_args += [
239     '--module-path', modules_compileClasspath.asPath,
240     '--add-modules', j11modules
241     ]
242      */
243   } else if (JAVA_VERSION.equals("12") || JAVA_VERSION.equals("13")) {
244     JAVA_INTEGER_VERSION = JAVA_VERSION
245     libDir = j11libDir
246     libDistDir = j11libDir
247     compile_source_compatibility = JAVA_VERSION
248     compile_target_compatibility = JAVA_VERSION
249     getdown_alt_java_min_version = getdown_alt_java11_min_version
250     getdown_alt_java_max_version = getdown_alt_java11_max_version
251     getdown_alt_multi_java_location = getdown_alt_java11_txt_multi_java_location
252     eclipse_java_runtime_name = string("JavaSE-11")
253     /* compile without modules -- using classpath libraries
254     additional_compiler_args += [
255     '--module-path', modules_compileClasspath.asPath,
256     '--add-modules', j11modules
257     ]
258      */
259   } else {
260     throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
261   }
262
263
264   // for install4j
265   macosJavaVMDir = string("${System.env.HOME}/buildtools/jre/openjdk-java_vm/getdown/macos-jre${JAVA_VERSION}/jre")
266   macosJavaVMTgz = string("${System.env.HOME}/buildtools/jre/openjdk-java_vm/install4j/tgz/macos-jre${JAVA_VERSION}.tar.gz")
267   windowsJavaVMDir = string("${System.env.HOME}/buildtools/jre/openjdk-java_vm/getdown/windows-jre${JAVA_VERSION}/jre")
268   windowsJavaVMTgz = string("${System.env.HOME}/buildtools/jre/openjdk-java_vm/install4j/tgz/windows-jre${JAVA_VERSION}.tar.gz")
269   install4jDir = string("${jalviewDir}/${install4jResourceDir}")
270   install4jConfFileName = string("jalview-installers-java${JAVA_VERSION}.install4j")
271   install4jConfFile = string("${install4jDir}/${install4jConfFileName}")
272
273
274   buildingHTML = string("${jalviewDir}/${docDir}/building.html")
275   helpFile = string("${classes}/${helpDir}/help.jhm")
276
277
278   relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
279   jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
280   jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
281   jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
282   jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
283   jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
284   jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
285   jalviewjsJalviewCoreName = jalviewjs_core_name
286   jalviewjsJalviewTemplateName = string(jalviewjs_name)
287
288   eclipseWorkspace = null
289   eclipseBinary = string("")
290   eclipseVersion = string("")
291   eclipseDebug = false
292   // ENDEXT
293 }
294
295
296 sourceSets {
297   main {
298     java {
299       srcDirs "${jalviewDir}/${sourceDir}"
300       outputDir = file(project.classes)
301     }
302
303     resources {
304       srcDirs "${jalviewDir}/${resourceDir}"
305     }
306
307     jar.destinationDir = file("${jalviewDir}/${packageDir}")
308
309     compileClasspath = files(sourceSets.main.java.outputDir)
310     compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
311
312     runtimeClasspath = compileClasspath
313   }
314
315   clover {
316     java {
317       srcDirs = [ cloverInstrDir ]
318       outputDir = file("${buildDir}/${cloverClassesDir}")
319     }
320
321     resources {
322       srcDirs = sourceSets.main.resources.srcDirs
323     }
324     compileClasspath = configurations.cloverRuntime + files( sourceSets.clover.java.outputDir )
325     compileClasspath += files(sourceSets.main.java.outputDir)
326     compileClasspath += sourceSets.main.compileClasspath
327     compileClasspath += fileTree(dir: "${jalviewDir}/${utilsDir}", include: ["**/*.jar"])
328     compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
329
330     runtimeClasspath = compileClasspath
331   }
332
333   test {
334     java {
335       srcDirs "${jalviewDir}/${testSourceDir}"
336       outputDir = file("${jalviewDir}/${testOutputDir}")
337     }
338
339     resources {
340       srcDirs = sourceSets.main.resources.srcDirs
341     }
342
343     compileClasspath = files( sourceSets.test.java.outputDir )
344
345     if (use_clover) {
346       compileClasspath += sourceSets.clover.compileClasspath
347     } else {
348       compileClasspath += files(sourceSets.main.java.outputDir)
349     }
350
351     compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
352     compileClasspath += fileTree(dir: "${jalviewDir}/${utilsDir}/testnglibs", include: ["**/*.jar"])
353     compileClasspath += fileTree(dir: "${jalviewDir}/${utilsDir}/testlibs", include: ["**/*.jar"])
354
355     runtimeClasspath = compileClasspath
356   }
357 }
358
359
360 // clover bits
361 dependencies {
362   if (use_clover) {
363     cloverCompile 'org.openclover:clover:4.3.1'
364     testCompile 'org.openclover:clover:4.3.1'
365   }
366 }
367
368
369 configurations {
370   cloverRuntime
371   cloverRuntime.extendsFrom cloverCompile
372 }
373
374 eclipse {
375   project {
376     name = eclipse_project_name
377
378     natures 'org.eclipse.jdt.core.javanature',
379     'org.eclipse.jdt.groovy.core.groovyNature',
380     'org.eclipse.buildship.core.gradleprojectnature'
381
382     buildCommand 'org.eclipse.jdt.core.javabuilder'
383     buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
384   }
385
386   classpath {
387     //defaultOutputDir = sourceSets.main.java.outputDir
388     def removeThese = []
389     configurations.each{
390       if (it.isCanBeResolved()) {
391         removeThese += it
392       }
393     }
394
395     minusConfigurations += removeThese
396     plusConfigurations = [ ]
397     file {
398
399       whenMerged { cp ->
400         def removeTheseToo = []
401         HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
402         cp.entries.each { entry ->
403           if (entry.kind == 'src') {
404             if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == sourceDir || entry.path == testSourceDir)) {
405               removeTheseToo += entry
406             } else {
407               alreadyAddedSrcPath.putAt(entry.path, true)
408             }
409           }
410         }
411         cp.entries.removeAll(removeTheseToo)
412
413         if (file("${jalviewDir}/${eclipse_bin_dir}/main").isDirectory()) {
414           cp.entries += new Output("${eclipse_bin_dir}/main")
415         }
416         if (file(helpParentDir).isDirectory()) {
417           cp.entries += new Library(fileReference(helpParentDir))
418         }
419         if (file(resourceDir).isDirectory()) {
420           cp.entries += new Library(fileReference(resourceDir))
421         }
422
423         HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
424
425         sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.each {
426           //don't want to add outputDir as eclipse is using its own output dir in bin/main
427           if (it.isDirectory() || ! it.exists()) {
428             // don't add dirs to classpath
429             return
430           }
431           def itPath = it.toString()
432           if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
433             // make relative path
434             itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
435           }
436           if (alreadyAddedLibPath.get(itPath)) {
437             //println("Not adding duplicate entry "+itPath)
438           } else {
439             //println("Adding entry "+itPath)
440             cp.entries += new Library(fileReference(itPath))
441             alreadyAddedLibPath.put(itPath, true)
442           }
443         }
444
445         //fileTree(dir: "$jalviewDir/$utilsDir", include: ["test*/*.jar"]).each {
446         sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
447           //no longer want to add outputDir as eclipse is using its own output dir in bin/main
448           if (it.isDirectory() || ! it.exists()) {
449             // don't add dirs to classpath
450             return false // groovy "continue" in .any closure
451           }
452
453           def itPath = it.toString()
454           if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
455             itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
456           }
457           if (alreadyAddedLibPath.get(itPath)) {
458             // don't duplicate
459           } else {
460             def lib = new Library(fileReference(itPath))
461             lib.entryAttributes["test"] = "true"
462             cp.entries += lib
463             alreadyAddedLibPath.put(itPath, true)
464           }
465         }
466
467       } // whenMerged
468
469     } // file
470
471     containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
472
473   } // classpath
474
475   jdt {
476     // for the IDE, use java 11 compatibility
477     sourceCompatibility = compile_source_compatibility
478     targetCompatibility = compile_target_compatibility
479     javaRuntimeName = eclipse_java_runtime_name
480
481     // add in jalview project specific properties/preferences into eclipse core preferences
482     file {
483       withProperties { props ->
484         def jalview_prefs = new Properties()
485         def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
486         jalview_prefs.load(ins)
487         ins.close()
488         jalview_prefs.forEach { t, v ->
489           if (props.getAt(t) == null) {
490             props.putAt(t, v)
491           }
492         }
493       }
494     }
495
496   } // jdt
497
498   synchronizationTasks "eclipseSynchronizationTask"
499   autoBuildTasks "eclipseAutoBuildTask"
500 }
501
502
503 task cloverInstr() {
504   // only instrument source, we build test classes as normal
505   inputs.files files (sourceSets.main.allJava) // , fileTree(dir:"$jalviewDir/$testSourceDir", include: ["**/*.java"]))
506   outputs.dir cloverInstrDir
507
508   doFirst {
509     delete cloverInstrDir
510     def argsList = ["--initstring", "${buildDir}/clover/clover.db",
511     "-d", "${buildDir}/${cloverSourcesInstrDir}"]
512     argsList.addAll(inputs.files.files.collect({ file ->
513       file.absolutePath
514     }))
515     String[] args = argsList.toArray()
516     println("About to instrument "+args.length +" files")
517     com.atlassian.clover.CloverInstr.mainImpl(args)
518   }
519 }
520
521
522 task cloverReport {
523   group = "Verification"
524     description = "Createst the Clover report"
525     inputs.dir "${buildDir}/clover"
526     outputs.dir "${reportsDir}/clover"
527     onlyIf {
528       file("${buildDir}/clover/clover.db").exists()
529     }
530   doFirst {
531     def argsList = ["--initstring", "${buildDir}/clover/clover.db",
532     "-o", "${reportsDir}/clover"]
533     String[] args = argsList.toArray()
534     com.atlassian.clover.reporters.html.HtmlReporter.runReport(args)
535
536     // and generate ${reportsDir}/clover/clover.xml
537     args = ["--initstring", "${buildDir}/clover/clover.db",
538     "-o", "${reportsDir}/clover/clover.xml"].toArray()
539     com.atlassian.clover.reporters.xml.XMLReporter.runReport(args)
540   }
541 }
542 // end clover bits
543
544
545 compileJava {
546
547   doFirst {
548     sourceCompatibility = compile_source_compatibility
549     targetCompatibility = compile_target_compatibility
550     options.compilerArgs = additional_compiler_args
551     print ("Setting target compatibility to "+targetCompatibility+"\n")
552   }
553
554 }
555
556
557 compileTestJava {
558   if (use_clover) {
559     dependsOn compileCloverJava
560     classpath += configurations.cloverRuntime
561   } else {
562     classpath += sourceSets.main.runtimeClasspath
563   }
564   doFirst {
565     sourceCompatibility = compile_source_compatibility
566     targetCompatibility = compile_target_compatibility
567     options.compilerArgs = additional_compiler_args
568     print ("Setting target compatibility to "+targetCompatibility+"\n")
569   }
570 }
571
572
573 compileCloverJava {
574
575   doFirst {
576     sourceCompatibility = compile_source_compatibility
577     targetCompatibility = compile_target_compatibility
578     options.compilerArgs += additional_compiler_args
579     print ("Setting target compatibility to "+targetCompatibility+"\n")
580   }
581   classpath += configurations.cloverRuntime
582 }
583
584
585 clean {
586   doFirst {
587     delete sourceSets.main.java.outputDir
588   }
589 }
590
591
592 cleanTest {
593   doFirst {
594     delete sourceSets.test.java.outputDir
595     delete cloverInstrDir
596   }
597 }
598
599
600 // format is a string like date.format("dd MMMM yyyy")
601 def getDate(format) {
602   def date = new Date()
603   return date.format(format)
604 }
605
606
607 task setGitVals {
608   def hashStdOut = new ByteArrayOutputStream()
609   exec {
610     commandLine "git", "rev-parse", "--short", "HEAD"
611     standardOutput = hashStdOut
612     ignoreExitValue true
613   }
614
615   def branchStdOut = new ByteArrayOutputStream()
616   exec {
617     commandLine "git", "rev-parse", "--abbrev-ref", "HEAD"
618     standardOutput = branchStdOut
619     ignoreExitValue true
620   }
621
622   gitHash = hashStdOut.toString().trim()
623   gitBranch = branchStdOut.toString().trim()
624
625   outputs.upToDateWhen { false }
626 }
627
628
629 task createBuildProperties(type: WriteProperties) {
630   dependsOn setGitVals
631   inputs.dir("${jalviewDir}/${sourceDir}")
632   inputs.dir("${jalviewDir}/${resourceDir}")
633   file(buildProperties).getParentFile().mkdirs()
634   outputFile (buildProperties)
635   // taking time specific comment out to allow better incremental builds
636   comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
637   //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
638   property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
639   property "VERSION", JALVIEW_VERSION
640   property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
641   outputs.file(outputFile)
642 }
643
644
645 task cleanBuildingHTML(type: Delete) {
646   doFirst {
647     delete buildingHTML
648   }
649 }
650
651
652 task convertBuildingMD(type: Exec) {
653   dependsOn cleanBuildingHTML
654   def buildingMD = "${jalviewDir}/${docDir}/building.md"
655   def css = "${jalviewDir}/${docDir}/github.css"
656
657   def pandoc = null
658   pandoc_exec.split(",").each {
659     if (file(it.trim()).exists()) {
660       pandoc = it.trim()
661       return true
662     }
663   }
664
665   def hostname = "hostname".execute().text.trim()
666   if ((pandoc == null || ! file(pandoc).exists()) && hostname.equals("jv-bamboo")) {
667     pandoc = System.getProperty("user.home")+"/buildtools/pandoc/bin/pandoc"
668   }
669
670   doFirst {
671     if (pandoc != null && file(pandoc).exists()) {
672         commandLine pandoc, '-s', '-o', buildingHTML, '--metadata', 'pagetitle="Building Jalview from Source"', '--toc', '-H', css, buildingMD
673     } else {
674         println("Cannot find pandoc. Skipping convert building.md to HTML")
675         throw new StopExecutionException()
676     }
677   }
678
679   ignoreExitValue true
680
681   inputs.file(buildingMD)
682   inputs.file(css)
683   outputs.file(buildingHTML)
684 }
685
686
687 clean {
688   doFirst {
689     delete buildingHTML
690   }
691 }
692
693
694 task syncDocs(type: Sync) {
695   dependsOn convertBuildingMD
696   def syncDir = "${classes}/${docDir}"
697   from fileTree("${jalviewDir}/${docDir}")
698   into syncDir
699
700 }
701
702
703 task copyHelp(type: Copy) {
704   def inputDir = "${jalviewDir}/${helpParentDir}/${helpDir}"
705   def outputDir = "${classes}/${helpDir}"
706   from(inputDir) {
707     exclude '**/*.gif'
708     exclude '**/*.jpg'
709     exclude '**/*.png'
710     filter(ReplaceTokens,
711       beginToken: '$$',
712       endToken: '$$',
713       tokens: [
714         'Version-Rel': JALVIEW_VERSION,
715         'Year-Rel': getDate("yyyy")
716       ]
717     )
718   }
719   from(inputDir) {
720     include '**/*.gif'
721     include '**/*.jpg'
722     include '**/*.png'
723   }
724   into outputDir
725
726   inputs.dir(inputDir)
727   outputs.files(helpFile)
728   outputs.dir(outputDir)
729 }
730
731
732 task syncLib(type: Sync) {
733   def syncDir = "${classes}/${libDistDir}"
734   from fileTree("${jalviewDir}/${libDistDir}")
735   into syncDir
736 }
737
738
739 task syncResources(type: Sync) {
740   from "${jalviewDir}/${resourceDir}"
741   include "**/*.*"
742   into "${classes}"
743   preserve {
744     include "**"
745   }
746 }
747
748
749 task prepare {
750   dependsOn syncResources
751   dependsOn syncDocs
752   dependsOn copyHelp
753 }
754
755
756 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
757 test {
758   dependsOn prepare
759   dependsOn compileJava
760   if (use_clover) {
761     dependsOn cloverInstr
762   }
763
764   if (use_clover) {
765     print("Running tests " + (use_clover?"WITH":"WITHOUT") + " clover [clover="+use_clover+"]\n")
766   }
767
768   useTestNG() {
769     includeGroups testngGroups
770     preserveOrder true
771     useDefaultListeners=true
772   }
773
774   workingDir = jalviewDir
775   //systemProperties 'clover.jar' System.properties.clover.jar
776   sourceCompatibility = compile_source_compatibility
777   targetCompatibility = compile_target_compatibility
778   jvmArgs += additional_compiler_args
779
780 }
781
782
783 task buildIndices(type: JavaExec) {
784   dependsOn copyHelp
785   classpath = sourceSets.main.compileClasspath
786   main = "com.sun.java.help.search.Indexer"
787   workingDir = "${classes}/${helpDir}"
788   def argDir = "html"
789   args = [ argDir ]
790   inputs.dir("${workingDir}/${argDir}")
791
792   outputs.dir("${classes}/doc")
793   outputs.dir("${classes}/help")
794   outputs.file("${workingDir}/JavaHelpSearch/DOCS")
795   outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
796   outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
797   outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
798   outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
799   outputs.file("${workingDir}/JavaHelpSearch/TMAP")
800 }
801
802
803 task compileLinkCheck(type: JavaCompile) {
804   options.fork = true
805   classpath = files("${jalviewDir}/${utilsDir}")
806   destinationDir = file("${jalviewDir}/${utilsDir}")
807   source = fileTree(dir: "${jalviewDir}/${utilsDir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
808
809   inputs.file("${jalviewDir}/${utilsDir}/HelpLinksChecker.java")
810   inputs.file("${jalviewDir}/${utilsDir}/HelpLinksChecker.java")
811   outputs.file("${jalviewDir}/${utilsDir}/HelpLinksChecker.class")
812   outputs.file("${jalviewDir}/${utilsDir}/BufferedLineReader.class")
813 }
814
815
816 task linkCheck(type: JavaExec) {
817   dependsOn prepare, compileLinkCheck
818
819   def helpLinksCheckerOutFile = file("${jalviewDir}/${utilsDir}/HelpLinksChecker.out")
820   classpath = files("${jalviewDir}/${utilsDir}")
821   main = "HelpLinksChecker"
822   workingDir = jalviewDir
823   def help = "${classes}/${helpDir}"
824   args = [ "${classes}/${helpDir}", "-nointernet" ]
825
826   def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
827   def errFOS = outFOS
828   standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
829     outFOS,
830     standardOutput)
831   errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
832     outFOS,
833     errorOutput)
834
835   inputs.dir("${classes}/${helpDir}")
836   outputs.file(helpLinksCheckerOutFile)
837 }
838
839 // import the pubhtmlhelp target
840 ant.properties.basedir = "${jalviewDir}"
841 ant.properties.helpBuildDir = "${jalviewDirAbsolutePath}/${classes}/${helpDir}"
842 ant.importBuild "${utilsDir}/publishHelp.xml"
843
844
845 task cleanPackageDir(type: Delete) {
846   doFirst {
847     delete fileTree(dir: "${jalviewDir}/${packageDir}", include: "*.jar")
848   }
849 }
850
851 jar {
852   dependsOn linkCheck
853   dependsOn buildIndices
854   dependsOn createBuildProperties
855
856   manifest {
857     attributes "Main-Class": mainClass,
858     "Permissions": "all-permissions",
859     "Application-Name": "Jalview Desktop",
860     "Codebase": application_codebase
861   }
862
863   destinationDir = file("${jalviewDir}/${packageDir}")
864   archiveName = rootProject.name+".jar"
865
866   exclude "cache*/**"
867   exclude "*.jar"
868   exclude "*.jar.*"
869   exclude "**/*.jar"
870   exclude "**/*.jar.*"
871
872   inputs.dir("${classes}")
873   outputs.file("${jalviewDir}/${packageDir}/${archiveName}")
874 }
875
876
877 task copyJars(type: Copy) {
878   from fileTree(dir: "${classes}", include: "**/*.jar").files
879   into "${jalviewDir}/${packageDir}"
880 }
881
882
883 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
884 task syncJars(type: Sync) {
885   from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
886   into "${jalviewDir}/${packageDir}"
887   preserve {
888     include jar.archiveName
889   }
890 }
891
892
893 task makeDist {
894   group = "build"
895   description = "Put all required libraries in dist"
896   // order of "cleanPackageDir", "copyJars", "jar" important!
897   jar.mustRunAfter cleanPackageDir
898   syncJars.mustRunAfter cleanPackageDir
899   dependsOn cleanPackageDir
900   dependsOn syncJars
901   dependsOn jar
902   outputs.dir("${jalviewDir}/${packageDir}")
903 }
904
905
906 task cleanDist {
907   dependsOn cleanPackageDir
908   dependsOn cleanTest
909   dependsOn clean
910 }
911
912 shadowJar {
913   group = "distribution"
914   if (buildDist) {
915     dependsOn makeDist
916   }
917   from ("${jalviewDir}/${libDistDir}") {
918     include("*.jar")
919   }
920   manifest {
921     attributes 'Implementation-Version': JALVIEW_VERSION
922   }
923   mainClassName = shadowJarMainClass
924   mergeServiceFiles()
925   classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
926   minimize()
927 }
928
929
930 task getdownWebsite() {
931   group = "distribution"
932   description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
933   if (buildDist) {
934     dependsOn makeDist
935   }
936
937   def getdownWebsiteResourceFilenames = []
938   def getdownTextString = ""
939   def getdownResourceDir = getdownResourceDir
940   def getdownAppDir = getdownAppDir
941   def getdownResourceFilenames = []
942
943   doFirst {
944     // clean the getdown website and files dir before creating getdown folders
945     delete getdownWebsiteDir
946     delete getdownFilesDir
947
948     copy {
949       from buildProperties
950       rename(build_properties_file, getdown_build_properties)
951       into getdownAppDir
952     }
953     getdownWebsiteResourceFilenames += "${getdown_app_dir}/${getdown_build_properties}"
954
955     // go through properties looking for getdown_txt_...
956     def props = project.properties.sort { it.key }
957     if (getdown_alt_java_min_version.length() > 0) {
958       props.put("getdown_txt_java_min_version", getdown_alt_java_min_version)
959     }
960     if (getdown_alt_java_max_version.length() > 0) {
961       props.put("getdown_txt_java_max_version", getdown_alt_java_max_version)
962     }
963     props.put("getdown_txt_multi_java_location", getdown_alt_multi_java_location)
964
965     props.put("getdown_txt_appbase", getdown_app_base)
966     props.each{ prop, val ->
967       if (prop.startsWith("getdown_txt_") && val != null) {
968         if (prop.startsWith("getdown_txt_multi_")) {
969           def key = prop.substring(18)
970           val.split(",").each{ v ->
971             def line = "${key} = ${v}\n"
972             getdownTextString += line
973           }
974         } else {
975           // file values rationalised
976           if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
977             def r = null
978             if (val.indexOf('/') == 0) {
979               // absolute path
980               r = file(val)
981             } else if (val.indexOf('/') > 0) {
982               // relative path (relative to jalviewDir)
983               r = file( "${jalviewDir}/${val}" )
984             }
985             if (r.exists()) {
986               val = "${getdown_resource_dir}/" + r.getName()
987               getdownWebsiteResourceFilenames += val
988               getdownResourceFilenames += r.getPath()
989             }
990           }
991           if (! prop.startsWith("getdown_txt_resource")) {
992             def line = prop.substring(12) + " = ${val}\n"
993             getdownTextString += line
994           }
995         }
996       }
997     }
998
999     getdownWebsiteResourceFilenames.each{ filename ->
1000       getdownTextString += "resource = ${filename}\n"
1001     }
1002     getdownResourceFilenames.each{ filename ->
1003       copy {
1004         from filename
1005         into getdownResourceDir
1006       }
1007     }
1008
1009     def codeFiles = []
1010     fileTree(file(packageDir)).each{ f ->
1011       if (f.isDirectory()) {
1012         def files = fileTree(dir: f, include: ["*"]).getFiles()
1013         codeFiles += files
1014       } else if (f.exists()) {
1015         codeFiles += f
1016       }
1017     }
1018     codeFiles.sort().each{f ->
1019       def name = f.getName()
1020       def line = "code = ${getdown_app_dir}/${name}\n"
1021       getdownTextString += line
1022       copy {
1023         from f.getPath()
1024         into getdownAppDir
1025       }
1026     }
1027
1028     // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
1029     /*
1030     if (JAVA_VERSION.equals("11")) {
1031     def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
1032     j11libFiles.sort().each{f ->
1033     def name = f.getName()
1034     def line = "code = ${getdown_j11lib_dir}/${name}\n"
1035     getdownTextString += line
1036     copy {
1037     from f.getPath()
1038     into getdownJ11libDir
1039     }
1040     }
1041     }
1042      */
1043
1044     // 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.
1045     //getdownTextString += "class = " + file(getdownLauncher).getName() + "\n"
1046     getdownTextString += "resource = ${getdown_launcher_new}\n"
1047     getdownTextString += "class = ${mainClass}\n"
1048
1049     def getdown_txt = file("${getdownWebsiteDir}/getdown.txt")
1050     getdown_txt.write(getdownTextString)
1051
1052     def launch_jvl = file("${getdownWebsiteDir}/${getdown_launch_jvl}")
1053     launch_jvl.write("appbase="+props.get("getdown_txt_appbase"))
1054
1055     copy {
1056       from getdownLauncher
1057       rename(file(getdownLauncher).getName(), getdown_launcher_new)
1058       into getdownWebsiteDir
1059     }
1060
1061     copy {
1062       from getdownLauncher
1063       if (file(getdownLauncher).getName() != getdown_launcher) {
1064         rename(file(getdownLauncher).getName(), getdown_launcher)
1065       }
1066       into getdownWebsiteDir
1067     }
1068
1069     if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
1070       copy {
1071         from getdown_txt
1072         from getdownLauncher
1073         from "${getdownWebsiteDir}/${getdown_build_properties}"
1074         if (file(getdownLauncher).getName() != getdown_launcher) {
1075           rename(file(getdownLauncher).getName(), getdown_launcher)
1076         }
1077         into getdownInstallDir
1078       }
1079
1080       copy {
1081         from getdownInstallDir
1082         into getdownFilesInstallDir
1083       }
1084     }
1085
1086     copy {
1087       from getdown_txt
1088       from launch_jvl
1089       from getdownLauncher
1090       from "${getdownWebsiteDir}/${getdown_build_properties}"
1091       if (file(getdownLauncher).getName() != getdown_launcher) {
1092         rename(file(getdownLauncher).getName(), getdown_launcher)
1093       }
1094       into getdownFilesDir
1095     }
1096
1097     copy {
1098       from getdownResourceDir
1099       into "${getdownFilesDir}/${getdown_resource_dir}"
1100     }
1101   }
1102
1103   if (buildDist) {
1104     inputs.dir("${jalviewDir}/${packageDir}")
1105   }
1106   outputs.dir(getdownWebsiteDir)
1107   outputs.dir(getdownFilesDir)
1108 }
1109
1110
1111 task getdownDigest(type: JavaExec) {
1112   group = "distribution"
1113   description = "Digest the getdown website folder"
1114   dependsOn getdownWebsite
1115   doFirst {
1116     classpath = files("${getdownWebsiteDir}/${getdown_launcher}")
1117   }
1118   main = "com.threerings.getdown.tools.Digester"
1119   args getdownWebsiteDir
1120   inputs.dir(getdownWebsiteDir)
1121   outputs.file("${getdownWebsiteDir}/digest2.txt")
1122 }
1123
1124
1125 task getdown() {
1126   group = "distribution"
1127   description = "Create the minimal and full getdown app folder for installers and website and create digest file"
1128   dependsOn getdownDigest
1129   doLast {
1130     if (reportRsyncCommand) {
1131       def fromDir = getdownWebsiteDir + (getdownWebsiteDir.endsWith('/')?'':'/')
1132       def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
1133       println "LIKELY RSYNC COMMAND:"
1134       println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
1135       if (RUNRSYNC == "true") {
1136         exec {
1137           commandLine "mkdir", "-p", toDir
1138         }
1139         exec {
1140           commandLine "rsync", "-avh", "--delete", fromDir, toDir
1141         }
1142       }
1143     }
1144   }
1145 }
1146
1147
1148 clean {
1149   doFirst {
1150     delete getdownWebsiteDir
1151     delete getdownFilesDir
1152   }
1153 }
1154
1155
1156 install4j {
1157   def install4jHomeDir = "/opt/install4j"
1158   def hostname = "hostname".execute().text.trim()
1159   if (hostname.equals("jv-bamboo")) {
1160     install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
1161   } else if (OperatingSystem.current().isMacOsX()) {
1162     install4jHomeDir = '/Applications/install4j.app/Contents/Resources/app'
1163     if (! file(install4jHomeDir).exists()) {
1164       install4jHomeDir = System.getProperty("user.home")+install4jHomeDir
1165     }
1166   } else if (OperatingSystem.current().isLinux()) {
1167     install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
1168   }
1169   installDir = file(install4jHomeDir)
1170   mediaTypes = Arrays.asList(install4jMediaTypes.split(","))
1171   if (install4jFaster.equals("true")) {
1172     faster = true
1173   }
1174 }
1175
1176
1177 task copyInstall4jTemplate(type: Copy) {
1178   from (install4jDir) {
1179     include install4jTemplate
1180     rename (install4jTemplate, install4jConfFileName)
1181     filter(ReplaceTokens,
1182       beginToken: '',
1183       endToken: '',
1184       tokens: [
1185         '9999999999': JAVA_VERSION
1186       ]
1187     )
1188     filter(ReplaceTokens,
1189       beginToken: '$$',
1190       endToken: '$$',
1191       tokens: [
1192         'JAVA_VERSION': JAVA_VERSION,
1193         'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
1194         'VERSION': JALVIEW_VERSION,
1195         'MACOS_JAVA_VM_DIR': macosJavaVMDir,
1196         'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
1197         'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
1198         'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
1199         'INSTALL4JINFOPLISTFILEASSOCIATIONS': install4jInfoPlistFileAssociations,
1200         'COPYRIGHT_MESSAGE': install4jCopyrightMessage,
1201         'MACOS_BUNDLE_ID': install4jMacOSBundleId,
1202         'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
1203         'GETDOWN_DIST_DIR': getdown_app_dir,
1204         'GETDOWN_ALT_DIR': getdown_app_dir_alt,
1205         'GETDOWN_INSTALL_DIR': getdown_install_dir
1206       ]
1207     )
1208     if (OSX_KEYPASS == "") {
1209       filter(ReplaceTokens,
1210         beginToken: 'codeSigning macEnabled="',
1211         endToken: '"',
1212         tokens: [
1213           'true': 'codeSigning macEnabled="false"'
1214         ]
1215       )
1216       filter(ReplaceTokens,
1217         beginToken: 'runPostProcessor="true" ',
1218         endToken: 'Processor',
1219         tokens: [
1220           'post': 'runPostProcessor="false" postProcessor'
1221         ]
1222       )
1223     }
1224   }
1225   into install4jDir
1226   outputs.files(install4jConfFile)
1227
1228   doLast {
1229     // include file associations in installer
1230     def installerFileAssociationsXml = file("${install4jDir}/${install4jInstallerFileAssociations}").text
1231     ant.replaceregexp(
1232       byline: false,
1233       flags: "s",
1234       match: '<action name="EXTENSIONS_REPLACED_BY_GRADLE".*?</action>',
1235       replace: installerFileAssociationsXml,
1236       file: install4jConfFile
1237     )
1238     /*
1239     // include uninstaller applescript app files in dmg
1240     def installerDMGUninstallerXml = file("$install4jDir/$install4jDMGUninstallerAppFiles").text
1241     ant.replaceregexp(
1242     byline: false,
1243     flags: "s",
1244     match: '<file name="UNINSTALL_OLD_JALVIEW_APP_REPLACED_IN_GRADLE" file=.*?>',
1245     replace: installerDMGUninstallerXml,
1246     file: install4jConfFile
1247     )
1248      */
1249   }
1250 }
1251
1252
1253 clean {
1254   doFirst {
1255     delete install4jConfFile
1256   }
1257 }
1258
1259
1260 task installers(type: com.install4j.gradle.Install4jTask) {
1261   group = "distribution"
1262   description = "Create the install4j installers"
1263   dependsOn getdown
1264   dependsOn copyInstall4jTemplate
1265   projectFile = file(install4jConfFile)
1266   variables = [majorVersion: version.substring(2, 11), build: 001, OSX_KEYSTORE: OSX_KEYSTORE, JSIGN_SH: JSIGN_SH]
1267   destination = "${jalviewDir}/${install4jBuildDir}/${JAVA_VERSION}"
1268   buildSelected = true
1269
1270   if (OSX_KEYPASS) {
1271     macKeystorePassword=OSX_KEYPASS
1272   }
1273
1274   doFirst {
1275     println("Using projectFile "+projectFile)
1276   }
1277
1278   inputs.dir(getdownWebsiteDir)
1279   inputs.file(install4jConfFile)
1280   inputs.dir(macosJavaVMDir)
1281   inputs.dir(windowsJavaVMDir)
1282   outputs.dir("${jalviewDir}/${install4jBuildDir}/${JAVA_VERSION}")
1283 }
1284
1285
1286 clean {
1287   doFirst {
1288     delete install4jConfFile
1289   }
1290 }
1291
1292
1293 task sourceDist (type: Tar) {
1294   
1295   def VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
1296   def outputFileName = "${project.name}_${VERSION_UNDERSCORES}.tar.gz"
1297   // cater for buildship < 3.1 [3.0.1 is max version in eclipse 2018-09]
1298   try {
1299     archiveFileName = outputFileName
1300   } catch (Exception e) {
1301     archiveName = outputFileName
1302   }
1303   
1304   compression Compression.GZIP
1305   
1306   into project.name
1307
1308   def EXCLUDE_FILES=["build/*","bin/*","test-output/","test-reports","tests","clover*/*"
1309   ,".*"
1310   ,"benchmarking/*"
1311   ,"**/.*"
1312   ,"*.class"
1313   ,"**/*.class","${j11modDir}/**/*.jar","appletlib","**/*locales"
1314   ,"*locales/**",
1315   ,"utils/InstallAnywhere"] 
1316   def PROCESS_FILES=[   "AUTHORS",
1317   "CITATION",
1318   "FEATURETODO",
1319   "JAVA-11-README",
1320   "FEATURETODO",
1321   "LICENSE",
1322   "**/README",
1323   "RELEASE",
1324   "THIRDPARTYLIBS","TESTNG",
1325   "build.gradle",
1326   "gradle.properties",
1327   "**/*.java",
1328   "**/*.html",
1329   "**/*.xml",
1330   "**/*.gradle",
1331   "**/*.groovy",
1332   "**/*.properties",
1333   "**/*.perl",
1334   "**/*.sh"]
1335
1336   from(jalviewDir) {
1337     exclude (EXCLUDE_FILES)
1338     include (PROCESS_FILES)
1339     filter(ReplaceTokens,
1340       beginToken: '$$',
1341       endToken: '$$',
1342       tokens: [
1343         'Version-Rel': JALVIEW_VERSION,
1344         'Year-Rel': getDate("yyyy")
1345       ]
1346     )
1347   }
1348   from(jalviewDir) {
1349     exclude (EXCLUDE_FILES)
1350     exclude (PROCESS_FILES)
1351     exclude ("appletlib")
1352     exclude ("**/*locales")
1353     exclude ("*locales/**")
1354     exclude ("utils/InstallAnywhere")
1355
1356     exclude (getdown_files_dir)
1357     exclude (getdown_website_dir)
1358
1359     // exluding these as not using jars as modules yet
1360     exclude ("${j11modDir}/**/*.jar")
1361   }
1362   //  from (jalviewDir) {
1363   //    // explicit includes for stuff that seemed to not get included
1364   //    include(fileTree("test/**/*."))
1365   //    exclude(EXCLUDE_FILES)
1366   //    exclude(PROCESS_FILES)
1367   //  }
1368 }
1369
1370
1371 task helppages  {
1372   dependsOn copyHelp
1373   dependsOn pubhtmlhelp
1374   
1375   inputs.dir("${classes}/${helpDir}")
1376   outputs.dir("${helpOutputDir}")
1377 }
1378
1379
1380 task j2sSetHeadlessBuild {
1381   doFirst {
1382     IN_ECLIPSE = false
1383   }
1384 }
1385
1386
1387 task jalviewjsSetEclipseWorkspace {
1388   def propKey = "jalviewjs_eclipse_workspace"
1389   def propVal = null
1390   if (project.hasProperty(propKey)) {
1391     propVal = project.getProperty(propKey)
1392     if (propVal.startsWith("~/")) {
1393       propVal = System.getProperty("user.home") + propVal.substring(1)
1394     }
1395   }
1396   def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
1397   def propsFile = file(propsFileName)
1398   def eclipseWsDir = propVal
1399   def props = new Properties()
1400
1401   if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
1402     def ins = new FileInputStream(propsFileName)
1403     props.load(ins)
1404     ins.close()
1405     if (props.getProperty(propKey, null) != null) {
1406       eclipseWsDir = props.getProperty(propKey)
1407     }
1408   }
1409
1410   def writeProps = false
1411   if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
1412     def tempDir = File.createTempDir()
1413     eclipseWsDir = tempDir.getAbsolutePath()
1414     writeProps = true
1415   }
1416   eclipseWorkspace = file(eclipseWsDir)
1417
1418   doFirst {
1419     // do not run a headless transpile when we claim to be in Eclipse
1420     if (IN_ECLIPSE) {
1421       println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
1422       throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
1423     } else {
1424       println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
1425     }
1426
1427     if (writeProps) {
1428       props.setProperty(propKey, eclipseWsDir)
1429       propsFile.parentFile.mkdirs()
1430       def bytes = new ByteArrayOutputStream()
1431       props.store(bytes, null)
1432       def propertiesString = bytes.toString()
1433       propsFile.text = propertiesString
1434     }
1435
1436     println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
1437   }
1438
1439   //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
1440   outputs.file(propsFileName)
1441   outputs.upToDateWhen { eclipseWorkspace.exists() }
1442 }
1443
1444
1445 task jalviewjsEclipsePaths {
1446   def eclipseProduct
1447
1448   def eclipseRoot = jalviewjs_eclipse_root
1449   if (eclipseRoot.startsWith("~/")) {
1450     eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
1451   }
1452   if (OperatingSystem.current().isMacOsX()) {
1453     eclipseRoot += "/Eclipse.app"
1454     eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
1455     eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
1456   } else if (OperatingSystem.current().isWindows()) { // check these paths!!
1457     if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
1458       eclipseRoot += "/eclipse.exe"
1459     }
1460     eclipseBinary = "${eclipseRoot}/eclipse"
1461     eclipseProduct = "${eclipseRoot}/.eclipseproduct"
1462   } else { // linux or unix
1463     if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
1464       eclipseRoot += "/eclipse"
1465     }
1466     eclipseBinary = "${eclipseRoot}/eclipse"
1467     eclipseProduct = "${eclipseRoot}/.eclipseproduct"
1468   }
1469
1470   eclipseVersion = "4.13" // default
1471   def assumedVersion = true
1472   if (file(eclipseProduct).exists()) {
1473     def fis = new FileInputStream(eclipseProduct)
1474     def props = new Properties()
1475     props.load(fis)
1476     eclipseVersion = props.getProperty("version")
1477     fis.close()
1478     assumedVersion = false
1479   }
1480   
1481   def propKey = "eclipse_debug"
1482   eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
1483
1484   doFirst {
1485     // do not run a headless transpile when we claim to be in Eclipse
1486     if (IN_ECLIPSE) {
1487       println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
1488       throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
1489     } else {
1490       println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
1491     }
1492
1493     if (!assumedVersion) {
1494       println("ECLIPSE VERSION=${eclipseVersion}")
1495     }
1496   }
1497 }
1498
1499
1500 task eclipseSetup {
1501   dependsOn eclipseProject
1502   dependsOn eclipseClasspath
1503   dependsOn eclipseJdt
1504 }
1505
1506
1507 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
1508 task jalviewjsEclipseCopyDropins(type: Copy) {
1509   dependsOn jalviewjsEclipsePaths
1510
1511   def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
1512   inputFiles += file("${jalviewDir}/${jalviewjs_j2s_plugin}")
1513   def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
1514
1515   from inputFiles
1516   into outputDir
1517 }
1518
1519
1520 // this eclipse -clean doesn't actually work
1521 task jalviewjsCleanEclipse(type: Exec) {
1522   dependsOn eclipseSetup
1523   dependsOn jalviewjsEclipsePaths
1524   dependsOn jalviewjsEclipseCopyDropins
1525
1526   executable(eclipseBinary)
1527   args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
1528   if (eclipseDebug) {
1529     args += "-debug"
1530   }
1531   args += "-l"
1532
1533   def inputString = """exit
1534 y
1535 """
1536   def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
1537   standardInput = inputByteStream
1538 }
1539
1540 /* not really working yet
1541 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
1542 */
1543
1544
1545 task jalviewjsTransferUnzipSwingJs {
1546   def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
1547
1548   doLast {
1549     copy {
1550       from zipTree(file_zip)
1551       into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
1552     }
1553   }
1554
1555   inputs.file file_zip
1556   outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
1557 }
1558
1559
1560 task jalviewjsTransferUnzipLib {
1561   def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
1562
1563   doLast {
1564     zipFiles.each { file_zip -> 
1565       copy {
1566         from zipTree(file_zip)
1567         into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
1568       }
1569     }
1570   }
1571
1572   inputs.files zipFiles
1573   outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
1574 }
1575
1576
1577 task jalviewjsTransferUnzipAllLibs {
1578   dependsOn jalviewjsTransferUnzipSwingJs
1579   dependsOn jalviewjsTransferUnzipLib
1580 }
1581
1582
1583 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
1584   group "JalviewJS"
1585   description "Create the .j2s file from the j2s.* properties"
1586
1587   outputFile ("${jalviewDir}/${jalviewjs_j2s_settings}")
1588   def j2s_props = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
1589   def siteDirProperty = "j2s.site.directory"
1590   def setSiteDir = false
1591   j2s_props.each { prop, val ->
1592     if (val != null) {
1593       if (prop == siteDirProperty) {
1594         if (!(val.startsWith('/') || val.startsWith("file://") )) {
1595           val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
1596         }
1597         setSiteDir = true
1598       }
1599       property(prop,val)
1600     }
1601     if (!setSiteDir) { // default site location, don't override specifically set property
1602       property(siteDirProperty,"${jalviewDir}/${jalviewjsTransferSiteJsDir}")
1603     }
1604   }
1605   inputs.properties(j2s_props)
1606   outputs.file(outputFile)
1607 }
1608
1609
1610 task jalviewjsEclipseSetup {
1611   dependsOn jalviewjsEclipseCopyDropins
1612   dependsOn jalviewjsSetEclipseWorkspace
1613   dependsOn jalviewjsCreateJ2sSettings
1614 }
1615
1616
1617 task jalviewjsSyncAllLibs (type: Sync) {
1618   dependsOn jalviewjsTransferUnzipAllLibs
1619   def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
1620   inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
1621   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
1622
1623   from inputFiles
1624   into outputDir
1625   def outputFiles = []
1626   rename { filename ->
1627     outputFiles += "${outputDir}/${filename}"
1628     null
1629   }
1630   preserve {
1631     include "**"
1632   }
1633   outputs.files outputFiles
1634   inputs.files inputFiles
1635 }
1636
1637
1638 task jalviewjsSyncResources (type: Sync) {
1639   def inputFiles = fileTree(dir: "${jalviewDir}/${resourceDir}")
1640   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
1641
1642   from inputFiles
1643   into outputDir
1644   def outputFiles = []
1645   rename { filename ->
1646     outputFiles += "${outputDir}/${filename}"
1647     null
1648   }
1649   preserve {
1650     include "**"
1651   }
1652   outputs.files outputFiles
1653   inputs.files inputFiles
1654 }
1655
1656
1657 task jalviewjsSyncSiteResources (type: Sync) {
1658   def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
1659   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
1660
1661   from inputFiles
1662   into outputDir
1663   def outputFiles = []
1664   rename { filename ->
1665     outputFiles += "${outputDir}/${filename}"
1666     null
1667   }
1668   preserve {
1669     include "**"
1670   }
1671   outputs.files outputFiles
1672   inputs.files inputFiles
1673 }
1674
1675
1676 task jalviewjsSyncBuildProperties (type: Sync) {
1677   dependsOn createBuildProperties
1678   def inputFiles = [file(buildProperties)]
1679   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
1680
1681   from inputFiles
1682   into outputDir
1683   def outputFiles = []
1684   rename { filename ->
1685     outputFiles += "${outputDir}/${filename}"
1686     null
1687   }
1688   preserve {
1689     include "**"
1690   }
1691   outputs.files outputFiles
1692   inputs.files inputFiles
1693 }
1694
1695
1696 task jalviewjsProjectImport(type: Exec) {
1697   dependsOn eclipseSetup
1698   dependsOn jalviewjsEclipsePaths
1699   dependsOn jalviewjsEclipseSetup
1700
1701   doFirst {
1702     // do not run a headless import when we claim to be in Eclipse
1703     if (IN_ECLIPSE) {
1704       println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
1705       throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
1706     } else {
1707       println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
1708     }
1709   }
1710
1711   //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
1712   def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
1713   executable(eclipseBinary)
1714   args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
1715   if (eclipseDebug) {
1716     args += "-debug"
1717   }
1718   args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
1719   if (!IN_ECLIPSE) {
1720     args += [ "-D${j2sHeadlessBuildProperty}=true" ]
1721   }
1722
1723   inputs.file("${jalviewDir}/.project")
1724   outputs.upToDateWhen { 
1725     file(projdir).exists()
1726   }
1727 }
1728
1729
1730 task jalviewjsTranspile(type: Exec) {
1731   dependsOn jalviewjsEclipseSetup 
1732   dependsOn jalviewjsProjectImport
1733   dependsOn jalviewjsEclipsePaths
1734
1735   doFirst {
1736     // do not run a headless transpile when we claim to be in Eclipse
1737     if (IN_ECLIPSE) {
1738       println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
1739       throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
1740     } else {
1741       println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
1742     }
1743   }
1744
1745   executable(eclipseBinary)
1746   args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
1747   if (eclipseDebug) {
1748     args += "-debug"
1749   }
1750   args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
1751
1752   def stdout
1753   def stderr
1754   doFirst {
1755     stdout = new ByteArrayOutputStream()
1756     stderr = new ByteArrayOutputStream()
1757
1758     def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
1759     def logOutFile = file(logOutFileName)
1760     logOutFile.createNewFile()
1761     logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
1762 BINARY: ${eclipseBinary}
1763 VERSION: ${eclipseVersion}
1764 WORKSPACE: ${eclipseWorkspace}
1765 DEBUG: ${eclipseDebug}
1766 ----
1767 """
1768     def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
1769     // combine stdout and stderr
1770     def logErrFOS = logOutFOS
1771
1772     if (jalviewjs_j2s_to_console.equals("true")) {
1773       standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1774         new org.apache.tools.ant.util.TeeOutputStream(
1775           logOutFOS,
1776           stdout),
1777         standardOutput)
1778       errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1779         new org.apache.tools.ant.util.TeeOutputStream(
1780           logErrFOS,
1781           stderr),
1782         errorOutput)
1783     } else {
1784       standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1785         logOutFOS,
1786         stdout)
1787       errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1788         logErrFOS,
1789         stderr)
1790     }
1791   }
1792
1793   doLast {
1794     if (stdout.toString().contains("Error processing ")) {
1795       // j2s did not complete transpile
1796       //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
1797       throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
1798     }
1799   }
1800
1801   inputs.dir("${jalviewDir}/${sourceDir}")
1802   outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
1803   outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
1804 }
1805
1806
1807 def jalviewjsCallCore(FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
1808
1809   def stdout = new ByteArrayOutputStream()
1810   def stderr = new ByteArrayOutputStream()
1811
1812   def coreFile = file(jsfile)
1813   def msg = ""
1814   msg = "Generating ${jsfile}"
1815   println(msg)
1816   logOutFile.createNewFile()
1817   logOutFile.append(msg+"\n")
1818
1819   def coreTop = file(prefixFile)
1820   def coreBottom = file(suffixFile)
1821   coreFile.getParentFile().mkdirs()
1822   coreFile.createNewFile()
1823   coreFile.write( coreTop.text )
1824   list.each {
1825     f ->
1826     if (f.exists()) {
1827       def t = f.text
1828       t.replaceAll("Clazz\\.","Clazz_")
1829       t.replaceAll("Class__","Clazz._")
1830       coreFile.append( t )
1831     } else {
1832       msg = "...file '"+f.getPath()+"' does not exist, skipping"
1833       println(msg)
1834       logOutFile.append(msg+"\n")
1835     }
1836   }
1837   coreFile.append( coreBottom.text )
1838
1839   msg = "Generating ${zjsfile}"
1840   println(msg)
1841   logOutFile.append(msg+"\n")
1842   def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
1843   def logErrFOS = logOutFOS
1844
1845   javaexec {
1846     classpath = files(["${jalviewDir}/tools/closure_compiler.jar"])
1847     args = [ "--js", jsfile, "--js_output_file", zjsfile ]
1848
1849     msg = "\nRunning '"+commandLine.join(' ')+"'\n"
1850     println(msg)
1851     logOutFile.append(msg+"\n")
1852
1853     if (logOutConsole) {
1854       standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1855         new org.apache.tools.ant.util.TeeOutputStream(
1856           logOutFOS,
1857           stdout),
1858         standardOutput)
1859         errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1860           new org.apache.tools.ant.util.TeeOutputStream(
1861             logErrFOS,
1862             stderr),
1863           errorOutput)
1864     } else {
1865       standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1866         logOutFOS,
1867         stdout)
1868         errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1869           logErrFOS,
1870           stderr)
1871     }
1872   }
1873   msg = "--"
1874   println(msg)
1875   logOutFile.append(msg+"\n")
1876 }
1877
1878
1879 task jalviewjsNoTranspileBuildAllCores {
1880   dependsOn jalviewjsTransferUnzipSwingJs
1881
1882   def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
1883   def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
1884   def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
1885   def prefixFile = "${jsDir}/core/coretop2.js"
1886   def suffixFile = "${jsDir}/core/corebottom2.js"
1887
1888   inputs.file prefixFile
1889   inputs.file suffixFile
1890
1891   def classlistFiles = []
1892   // add the classlists found int the jalviewjs_classlists_dir
1893   fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
1894     file ->
1895     def name = file.getName() - ".txt"
1896     classlistFiles += [
1897       'file': file,
1898       'name': name
1899     ]
1900   }
1901
1902   // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
1903   classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
1904   classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
1905
1906   def classlists = []
1907
1908   classlistFiles.each {
1909     hash ->
1910
1911     def file = hash['file']
1912     if (! file.exists()) {
1913       println("...classlist file '"+file.getPath()+"' does not exist, skipping")
1914       return false // this is a "continue" in groovy .each closure
1915     }
1916     def name = hash['name']
1917     if (name == null) {
1918       name = file.getName() - ".txt"
1919     }
1920
1921     def filelist = []
1922     file.eachLine {
1923       line ->
1924         filelist += line
1925     }
1926     def list = fileTree(dir: j2sDir, includes: filelist)
1927
1928     def jsfile = "${outputDir}/core${name}.js"
1929     def zjsfile = "${outputDir}/core${name}.z.js"
1930
1931     classlists += [
1932     'jsfile': jsfile,
1933     'zjsfile': zjsfile,
1934     'list': list
1935     ]
1936
1937     inputs.file(file)
1938     inputs.files(list)
1939     outputs.file(jsfile)
1940     outputs.file(zjsfile)
1941   }
1942   
1943   // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
1944   def stevesoftClasslist = [
1945     'jsfile': "${outputDir}/core_stevesoft.js",
1946     'zjsfile': "${outputDir}/core_stevesoft.z.js",
1947     'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js")
1948   ]
1949   classlists += stevesoftClasslist
1950   inputs.files(stevesoftClasslist['list'])
1951   outputs.file(stevesoftClasslist['jsfile'])
1952   outputs.file(stevesoftClasslist['zjsfile'])
1953
1954   doFirst {
1955     def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
1956     logOutFile.getParentFile().mkdirs()
1957     logOutFile.createNewFile()
1958     logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsNoTranspileBuildAllCores\n----\n")
1959
1960     classlists.each {
1961       jalviewjsCallCore(it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
1962     }
1963   }
1964
1965 }
1966
1967
1968 jalviewjsNoTranspileBuildAllCores.mustRunAfter jalviewjsTranspile
1969
1970
1971 task jalviewjsBuildAllCores {
1972   group "JalviewJS"
1973   description "Build the core js lib closures listed in the classlists dir"
1974   dependsOn jalviewjsTranspile
1975   dependsOn jalviewjsNoTranspileBuildAllCores
1976 }
1977
1978
1979 def jalviewjsJalviewCoreHtmlFile
1980 task jalviewjsNoTranspilePublishCoreTemplate(type: Sync) {
1981   dependsOn jalviewjsNoTranspileBuildAllCores
1982
1983   def inputFile = file("${jalviewDir}/${j2s_template_html}")
1984   def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
1985
1986   from inputFile
1987   into outputDir
1988   def outputFiles = []
1989   jalviewjsJalviewCoreHtmlFile = "${jalviewjsJalviewTemplateName}_${jalviewjsJalviewCoreName}.html"
1990   rename { filename ->
1991     outputFiles += "${outputDir}/${filename}"
1992     if (filename.equals(inputFile.getName())) {
1993       return jalviewjsJalviewCoreHtmlFile 
1994     }
1995     return null
1996   }
1997   filter(ReplaceTokens,
1998     beginToken: '_',
1999     endToken: '_',
2000     tokens: [
2001       'MAIN': '"'+mainClass+'"',
2002       'CODE': "null",
2003       'NAME': jalviewjsJalviewTemplateName
2004     ]
2005   )
2006   filter(ReplaceTokens,
2007     beginToken: '',
2008     endToken: '',
2009     tokens: [
2010       'NONE': jalviewjsJalviewCoreName
2011     ]
2012   )
2013   preserve {
2014     include "**"
2015   }
2016   outputs.files outputFiles
2017   inputs.files inputFile
2018 }
2019
2020
2021 task jalviewjsPublishCoreTemplate {
2022   dependsOn jalviewjsTranspile
2023   dependsOn jalviewjsPublishCoreTemplate
2024 }
2025
2026
2027 task jalviewjsNoTranspileSyncCore (type: Sync) {
2028   dependsOn jalviewjsNoTranspileBuildAllCores
2029   dependsOn jalviewjsNoTranspilePublishCoreTemplate
2030   def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
2031   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2032
2033   from inputFiles
2034   into outputDir
2035   def outputFiles = []
2036   rename { filename ->
2037     outputFiles += "${outputDir}/${filename}"
2038     null
2039   }
2040   preserve {
2041     include "**"
2042   }
2043   outputs.files outputFiles
2044   inputs.files inputFiles
2045 }
2046
2047
2048 task jalviewjsSyncCore (type: Sync) {
2049   dependsOn jalviewjsTranspile
2050   dependsOn jalviewjsNoTranspileSyncCore
2051   dependsOn "jalviewjsBuildAllCores"
2052 }
2053
2054
2055 // this Copy version of TransferSiteJs will delete anything else in the target dir
2056 task jalviewjsCopyTransferSiteJs(type: Copy) {
2057   dependsOn jalviewjsTranspile
2058   from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
2059   into "${jalviewDir}/${jalviewjsSiteDir}"
2060 }
2061
2062
2063 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
2064 task jalviewjsNoTranspileSyncTransferSiteJs(type: Sync) {
2065   from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
2066   include "**/*.*"
2067   into "${jalviewDir}/${jalviewjsSiteDir}"
2068   preserve {
2069     include "**"
2070   }
2071 }
2072
2073 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
2074 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
2075 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
2076 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
2077
2078 jalviewjsSyncAllLibs.mustRunAfter jalviewjsNoTranspileSyncTransferSiteJs
2079 jalviewjsSyncResources.mustRunAfter jalviewjsNoTranspileSyncTransferSiteJs
2080 jalviewjsSyncSiteResources.mustRunAfter jalviewjsNoTranspileSyncTransferSiteJs
2081 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsNoTranspileSyncTransferSiteJs
2082
2083
2084 task jalviewjsNoTranspilePrepareSite {
2085   dependsOn jalviewjsSyncAllLibs
2086   dependsOn jalviewjsSyncResources
2087   dependsOn jalviewjsSyncSiteResources
2088   dependsOn jalviewjsSyncBuildProperties
2089   dependsOn jalviewjsNoTranspileSyncCore
2090 }
2091
2092
2093 task jalviewjsPrepareSite {
2094   group "JalviewJS"
2095   description "Prepares the website folder including unzipping files and copying resources"
2096   dependsOn jalviewjsSyncAllLibs
2097   dependsOn jalviewjsSyncResources
2098   dependsOn jalviewjsSyncSiteResources
2099   dependsOn jalviewjsSyncBuildProperties
2100   dependsOn jalviewjsSyncCore
2101 }
2102
2103
2104 task jalviewjsBuildSite {
2105   group "JalviewJS"
2106   description "Builds the whole website including transpiled code"
2107   dependsOn jalviewjsCopyTransferSiteJs
2108   dependsOn jalviewjsPrepareSite
2109 }
2110
2111
2112 task cleanJalviewjsSite {
2113   doFirst {
2114     delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
2115     delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2116     delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2117     delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
2118     delete "${jalviewDir}/${jalviewjsSiteDir}"
2119   }
2120 }
2121
2122
2123 task jalviewjsSiteTar(type: Tar) {
2124   group "JalviewJS"
2125   description "Creates a tar.gz file for the website"
2126   dependsOn jalviewjsBuildSite
2127   def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
2128   try {
2129     archiveFileName = outputFilename
2130   } catch (Exception e) {
2131     archiveName = outputFilename
2132   }
2133
2134   compression Compression.GZIP
2135
2136   from "${jalviewDir}/${jalviewjsSiteDir}"
2137   into jalviewjs_site_dir // this is inside the tar file
2138
2139   inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
2140 }
2141
2142
2143 task jalviewjsServer {
2144   group "JalviewJS"
2145   def filename = "jalviewjsTest.html"
2146   description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
2147   def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
2148   doLast {
2149
2150     SimpleHttpFileServerFactory factory = new SimpleHttpFileServerFactory()
2151     def port = Integer.valueOf(jalviewjs_server_port)
2152     def start = port
2153     def running = false
2154     def url
2155     def urlcore
2156     while(port < start+1000 && !running) {
2157       try {
2158         def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
2159         def jalviewjsServer = factory.start(doc_root, port)
2160         running = true
2161         url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
2162         urlcore = jalviewjsServer.getResourceUrl(jalviewjsJalviewCoreHtmlFile)
2163         println("SERVER STARTED with document root ${doc_root}.")
2164         println("Go to "+url+" . Run  gradle --stop  to stop (kills all gradle daemons).")
2165         println("For debug: "+url+"?j2sdebug")
2166         println("For core: "+urlcore)
2167
2168         file(htmlFile).text = """
2169         <p><a href="${url}">JalviewJS Test. &lt;${url}&gt;</a></p>
2170         <p><a href="${url}?j2sdebug">JalviewJS Test with debug. &lt;${url}?j2sdebug&lt;</a></p>
2171         <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} Core Test. &lt;${urlcore}&gt;</a></p>
2172         """
2173
2174       } catch (Exception e) {
2175         port++;
2176       }
2177     }
2178
2179   }
2180
2181   outputs.file(htmlFile)
2182   outputs.upToDateWhen({false})
2183 }
2184
2185
2186 task cleanJalviewjsAll {
2187   group "JalviewJS"
2188   description "Delete all configuration and build artifacts to do with JalviewJS build"
2189   dependsOn cleanJalviewjsSite
2190   dependsOn jalviewjsEclipsePaths
2191   
2192   doFirst {
2193     delete "${jalviewDir}/${jalviewjsBuildDir}"
2194     delete "${jalviewDir}/${eclipse_bin_dir}"
2195     if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
2196       delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
2197     }
2198     delete "${jalviewDir}/${jalviewjs_j2s_settings}"
2199   }
2200
2201   outputs.upToDateWhen( { false } )
2202 }
2203
2204
2205
2206 task jalviewjsIDE_CopyTransferSiteJs(type: Copy) {
2207   from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
2208   into "${jalviewDir}/${jalviewjsSiteDir}"
2209 }
2210
2211
2212 task jalviewjsIDE_j2sFile {
2213   group "00 JalviewJS in Eclipse"
2214   description "Creates the .j2s file"
2215   dependsOn jalviewjsCreateJ2sSettings
2216 }
2217
2218
2219 task jalviewjsIDE_BuildAllCores {
2220   group "00 JalviewJS in Eclipse"
2221   description "Build the core js lib closures listed in the classlists dir"
2222   dependsOn jalviewjsNoTranspileBuildAllCores
2223 }
2224
2225
2226 task jalviewjsIDE_AssembleSite {
2227   group "00 JalviewJS in Eclipse"
2228   description "Assembles the Eclipse transpiled site and unzips supporting zipfiles"
2229   dependsOn jalviewjsIDE_CopyTransferSiteJs
2230   dependsOn jalviewjsNoTranspilePrepareSite
2231 }
2232
2233
2234 task jalviewjsIDE_SiteClean {
2235   group "00 JalviewJS in Eclipse"
2236   description "Deletes the Eclipse transpiled site"
2237   dependsOn cleanJalviewjsSite
2238 }
2239
2240
2241 task jalviewjsIDE_Server {
2242   group "00 JalviewJS in Eclipse"
2243   description "Starts a webserver on localhost to test the website"
2244   dependsOn jalviewjsServer
2245 }
2246
2247
2248 // buildship runs this at import
2249 task eclipseSynchronizationTask {
2250   dependsOn eclipseSetup
2251   dependsOn jalviewjsIDE_j2sFile
2252 }
2253
2254
2255 // buildship runs this at build time
2256 task eclipseAutoBuildTask {
2257   dependsOn jalviewjsNoTranspileSyncTransferSiteJs
2258   dependsOn jalviewjsNoTranspilePrepareSite
2259 }
2260
2261
2262
2263
2264
2265
2266
2267
2268 task jalviewjs {
2269   group "JalviewJS"
2270   description "Build the site"
2271   dependsOn jalviewjsBuildSite
2272 }