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