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