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