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