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