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