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