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