JAL-3754 Fixed jar task creating strange dir because of outputs.file()
[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     println("Creating ${htmlFilePath}")
1088     htmlFile.text = htmlText
1089   }
1090 }
1091
1092
1093 task copyDocs(type: Copy) {
1094   def inputDir = "${jalviewDir}/${doc_dir}"
1095   def outputDir = "${docBuildDir}/${doc_dir}"
1096   from(inputDir) {
1097     include('**/*.txt')
1098     include('**/*.md')
1099     include('**/*.html')
1100     include('**/*.xml')
1101     filter(ReplaceTokens,
1102       beginToken: '$$',
1103       endToken: '$$',
1104       tokens: [
1105         'Version-Rel': JALVIEW_VERSION,
1106         'Year-Rel': getDate("yyyy")
1107       ]
1108     )
1109   }
1110   from(inputDir) {
1111     exclude('**/*.txt')
1112     exclude('**/*.md')
1113     exclude('**/*.html')
1114     exclude('**/*.xml')
1115   }
1116   into outputDir
1117
1118   inputs.dir(inputDir)
1119   outputs.dir(outputDir)
1120 }
1121
1122
1123 task convertMdFiles {
1124   dependsOn copyDocs
1125   def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1126   def cssFile = file("${jalviewDir}/${flexmark_css}")
1127
1128   doLast {
1129     convertMdToHtml(mdFiles, cssFile)
1130   }
1131
1132   inputs.files(mdFiles)
1133   inputs.file(cssFile)
1134
1135   def htmlFiles = []
1136   mdFiles.each { mdFile ->
1137     def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1138     htmlFiles.add(file(htmlFilePath))
1139   }
1140   outputs.files(htmlFiles)
1141 }
1142
1143
1144 task copyHelp(type: Copy) {
1145   def inputDir = helpSourceDir
1146   def outputDir = "${helpBuildDir}/${help_dir}"
1147   from(inputDir) {
1148     include('**/*.txt')
1149     include('**/*.md')
1150     include('**/*.html')
1151     include('**/*.hs')
1152     include('**/*.xml')
1153     include('**/*.jhm')
1154     filter(ReplaceTokens,
1155       beginToken: '$$',
1156       endToken: '$$',
1157       tokens: [
1158         'Version-Rel': JALVIEW_VERSION,
1159         'Year-Rel': getDate("yyyy")
1160       ]
1161     )
1162   }
1163   from(inputDir) {
1164     exclude('**/*.txt')
1165     exclude('**/*.md')
1166     exclude('**/*.html')
1167     exclude('**/*.hs')
1168     exclude('**/*.xml')
1169     exclude('**/*.jhm')
1170   }
1171   into outputDir
1172
1173   inputs.dir(inputDir)
1174   outputs.files(helpFile)
1175   outputs.dir(outputDir)
1176 }
1177
1178
1179 task copyResources(type: Copy) {
1180   def inputDir = resourceDir
1181   def outputDir = resourcesBuildDir
1182   from(inputDir) {
1183     include('**/*.txt')
1184     include('**/*.md')
1185     include('**/*.html')
1186     include('**/*.xml')
1187     filter(ReplaceTokens,
1188       beginToken: '$$',
1189       endToken: '$$',
1190       tokens: [
1191         'Version-Rel': JALVIEW_VERSION,
1192         'Year-Rel': getDate("yyyy")
1193       ]
1194     )
1195   }
1196   from(inputDir) {
1197     exclude('**/*.txt')
1198     exclude('**/*.md')
1199     exclude('**/*.html')
1200     exclude('**/*.xml')
1201   }
1202   into outputDir
1203
1204   inputs.dir(inputDir)
1205   outputs.dir(outputDir)
1206 }
1207
1208
1209 task createBuildProperties(type: WriteProperties) {
1210   dependsOn copyResources
1211   group = "build"
1212   description = "Create the ${buildProperties} file"
1213   
1214   inputs.dir(sourceDir)
1215   inputs.dir(resourcesBuildDir)
1216   outputFile (buildProperties)
1217   // taking time specific comment out to allow better incremental builds
1218   comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1219   //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1220   property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1221   property "VERSION", JALVIEW_VERSION
1222   property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1223   outputs.file(outputFile)
1224 }
1225
1226
1227 task buildIndices(type: JavaExec) {
1228   dependsOn copyHelp
1229   classpath = sourceSets.main.compileClasspath
1230   main = "com.sun.java.help.search.Indexer"
1231   workingDir = "${helpBuildDir}/${help_dir}"
1232   def argDir = "html"
1233   args = [ argDir ]
1234   inputs.dir("${workingDir}/${argDir}")
1235
1236   outputs.dir("${classesDir}/doc")
1237   outputs.dir("${classesDir}/help")
1238   outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1239   outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1240   outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1241   outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1242   outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1243   outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1244 }
1245
1246
1247 task prepare {
1248   dependsOn copyResources
1249   dependsOn copyDocs
1250   dependsOn copyHelp
1251   dependsOn createBuildProperties
1252   dependsOn convertMdFiles
1253   dependsOn buildIndices
1254 }
1255
1256
1257 compileJava.dependsOn prepare
1258 run.dependsOn compileJava
1259 //run.dependsOn prepare
1260
1261
1262 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1263 test {
1264   dependsOn prepare
1265
1266   if (useClover) {
1267     dependsOn cloverClasses
1268    } else { //?
1269     dependsOn compileJava //?
1270   }
1271
1272   useTestNG() {
1273     includeGroups testng_groups
1274     excludeGroups testng_excluded_groups
1275     preserveOrder true
1276     useDefaultListeners=true
1277   }
1278
1279   maxHeapSize = "1024m"
1280
1281   workingDir = jalviewDir
1282   def testLaf = project.findProperty("test_laf")
1283   if (testLaf != null) {
1284     println("Setting Test LaF to '${testLaf}'")
1285     systemProperty "laf", testLaf
1286   }
1287   sourceCompatibility = compile_source_compatibility
1288   targetCompatibility = compile_target_compatibility
1289   jvmArgs += additional_compiler_args
1290
1291   doFirst {
1292     if (useClover) {
1293       println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1294     }
1295   }
1296 }
1297
1298
1299 task compileLinkCheck(type: JavaCompile) {
1300   options.fork = true
1301   classpath = files("${jalviewDir}/${utils_dir}")
1302   destinationDir = file("${jalviewDir}/${utils_dir}")
1303   source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1304
1305   inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1306   inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1307   outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1308   outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1309 }
1310
1311
1312 task linkCheck(type: JavaExec) {
1313   dependsOn prepare
1314   dependsOn compileLinkCheck
1315
1316   def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1317   classpath = files("${jalviewDir}/${utils_dir}")
1318   main = "HelpLinksChecker"
1319   workingDir = jalviewDir
1320   args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1321
1322   def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1323   def errFOS = outFOS
1324   standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1325     outFOS,
1326     standardOutput)
1327   errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1328     outFOS,
1329     errorOutput)
1330
1331   inputs.dir(helpBuildDir)
1332   outputs.file(helpLinksCheckerOutFile)
1333 }
1334
1335
1336 // import the pubhtmlhelp target
1337 ant.properties.basedir = "${jalviewDir}"
1338 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1339 ant.importBuild "${utils_dir}/publishHelp.xml"
1340
1341
1342 task cleanPackageDir(type: Delete) {
1343   doFirst {
1344     delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1345   }
1346 }
1347
1348
1349 jar {
1350   dependsOn prepare
1351   dependsOn linkCheck
1352
1353   manifest {
1354     attributes "Main-Class": main_class,
1355     "Permissions": "all-permissions",
1356     "Application-Name": install4jApplicationName,
1357     "Codebase": application_codebase,
1358     "Implementation-Version": JALVIEW_VERSION
1359   }
1360
1361   def outputDir = "${jalviewDir}/${package_dir}"
1362   destinationDirectory = file(outputDir)
1363   archiveFileName = rootProject.name+".jar"
1364
1365   exclude "cache*/**"
1366   exclude "*.jar"
1367   exclude "*.jar.*"
1368   exclude "**/*.jar"
1369   exclude "**/*.jar.*"
1370
1371   inputs.dir(sourceSets.main.java.outputDir)
1372   sourceSets.main.resources.srcDirs.each{ dir ->
1373     inputs.dir(dir)
1374   }
1375   outputs.file("${outputDir}/${archiveFileName}")
1376 }
1377
1378
1379 task copyJars(type: Copy) {
1380   from fileTree(dir: classesDir, include: "**/*.jar").files
1381   into "${jalviewDir}/${package_dir}"
1382 }
1383
1384
1385 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1386 task syncJars(type: Sync) {
1387   dependsOn jar
1388   from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1389   into "${jalviewDir}/${package_dir}"
1390   preserve {
1391     include jar.archiveFileName.getOrNull()
1392   }
1393 }
1394
1395
1396 task makeDist {
1397   group = "build"
1398   description = "Put all required libraries in dist"
1399   // order of "cleanPackageDir", "copyJars", "jar" important!
1400   jar.mustRunAfter cleanPackageDir
1401   syncJars.mustRunAfter cleanPackageDir
1402   dependsOn cleanPackageDir
1403   dependsOn syncJars
1404   dependsOn jar
1405   outputs.dir("${jalviewDir}/${package_dir}")
1406 }
1407
1408
1409 task cleanDist {
1410   dependsOn cleanPackageDir
1411   dependsOn cleanTest
1412   dependsOn clean
1413 }
1414
1415
1416 shadowJar {
1417   group = "distribution"
1418   description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1419   if (buildDist) {
1420     dependsOn makeDist
1421   }
1422   from ("${jalviewDir}/${libDistDir}") {
1423     include("*.jar")
1424   }
1425   manifest {
1426     attributes "Implementation-Version": JALVIEW_VERSION,
1427     "Application-Name": install4jApplicationName
1428   }
1429   mainClassName = shadow_jar_main_class
1430   mergeServiceFiles()
1431   classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1432   minimize()
1433 }
1434
1435
1436 task getdownWebsite() {
1437   group = "distribution"
1438   description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1439   if (buildDist) {
1440     dependsOn makeDist
1441   }
1442
1443   def getdownWebsiteResourceFilenames = []
1444   def getdownTextString = ""
1445   def getdownResourceDir = getdownResourceDir
1446   def getdownResourceFilenames = []
1447
1448   doFirst {
1449     // clean the getdown website and files dir before creating getdown folders
1450     delete getdownWebsiteDir
1451     delete getdownFilesDir
1452
1453     copy {
1454       from buildProperties
1455       rename(build_properties_file, getdown_build_properties)
1456       into getdownAppDir
1457     }
1458     getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1459
1460     // set some getdown_txt_ properties then go through all properties looking for getdown_txt_...
1461     def props = project.properties.sort { it.key }
1462     if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1463       props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1464     }
1465     if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1466       props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1467     }
1468     if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1469       props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1470     }
1471
1472     props.put("getdown_txt_title", jalview_name)
1473     props.put("getdown_txt_ui.name", install4jApplicationName)
1474
1475     // start with appbase
1476     getdownTextString += "appbase = ${getdownAppBase}\n"
1477     props.each{ prop, val ->
1478       if (prop.startsWith("getdown_txt_") && val != null) {
1479         if (prop.startsWith("getdown_txt_multi_")) {
1480           def key = prop.substring(18)
1481           val.split(",").each{ v ->
1482             def line = "${key} = ${v}\n"
1483             getdownTextString += line
1484           }
1485         } else {
1486           // file values rationalised
1487           if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1488             def r = null
1489             if (val.indexOf('/') == 0) {
1490               // absolute path
1491               r = file(val)
1492             } else if (val.indexOf('/') > 0) {
1493               // relative path (relative to jalviewDir)
1494               r = file( "${jalviewDir}/${val}" )
1495             }
1496             if (r.exists()) {
1497               val = "${getdown_resource_dir}/" + r.getName()
1498               getdownWebsiteResourceFilenames += val
1499               getdownResourceFilenames += r.getPath()
1500             }
1501           }
1502           if (! prop.startsWith("getdown_txt_resource")) {
1503             def line = prop.substring(12) + " = ${val}\n"
1504             getdownTextString += line
1505           }
1506         }
1507       }
1508     }
1509
1510     getdownWebsiteResourceFilenames.each{ filename ->
1511       getdownTextString += "resource = ${filename}\n"
1512     }
1513     getdownResourceFilenames.each{ filename ->
1514       copy {
1515         from filename
1516         into getdownResourceDir
1517       }
1518     }
1519
1520     def codeFiles = []
1521     fileTree(file(package_dir)).each{ f ->
1522       if (f.isDirectory()) {
1523         def files = fileTree(dir: f, include: ["*"]).getFiles()
1524         codeFiles += files
1525       } else if (f.exists()) {
1526         codeFiles += f
1527       }
1528     }
1529     codeFiles.sort().each{f ->
1530       def name = f.getName()
1531       def line = "code = ${getdownAppDistDir}/${name}\n"
1532       getdownTextString += line
1533       copy {
1534         from f.getPath()
1535         into getdownAppDir
1536       }
1537     }
1538
1539     // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
1540     /*
1541     if (JAVA_VERSION.equals("11")) {
1542     def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
1543     j11libFiles.sort().each{f ->
1544     def name = f.getName()
1545     def line = "code = ${getdown_j11lib_dir}/${name}\n"
1546     getdownTextString += line
1547     copy {
1548     from f.getPath()
1549     into getdownJ11libDir
1550     }
1551     }
1552     }
1553      */
1554
1555     // 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.
1556     //getdownTextString += "class = " + file(getdownLauncher).getName() + "\n"
1557     getdownTextString += "resource = ${getdown_launcher_new}\n"
1558     getdownTextString += "class = ${main_class}\n"
1559
1560     def getdown_txt = file("${getdownWebsiteDir}/getdown.txt")
1561     getdown_txt.write(getdownTextString)
1562
1563     def getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
1564     def launchJvl = file("${getdownWebsiteDir}/${getdownLaunchJvl}")
1565     launchJvl.write("appbase=${getdownAppBase}")
1566
1567     copy {
1568       from getdownLauncher
1569       rename(file(getdownLauncher).getName(), getdown_launcher_new)
1570       into getdownWebsiteDir
1571     }
1572
1573     copy {
1574       from getdownLauncher
1575       if (file(getdownLauncher).getName() != getdown_launcher) {
1576         rename(file(getdownLauncher).getName(), getdown_launcher)
1577       }
1578       into getdownWebsiteDir
1579     }
1580
1581     if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
1582       copy {
1583         from getdown_txt
1584         from getdownLauncher
1585         from "${getdownWebsiteDir}/${getdown_build_properties}"
1586         if (file(getdownLauncher).getName() != getdown_launcher) {
1587           rename(file(getdownLauncher).getName(), getdown_launcher)
1588         }
1589         into getdownInstallDir
1590       }
1591
1592       copy {
1593         from getdownInstallDir
1594         into getdownFilesInstallDir
1595       }
1596     }
1597
1598     copy {
1599       from getdown_txt
1600       from launchJvl
1601       from getdownLauncher
1602       from "${getdownWebsiteDir}/${getdown_build_properties}"
1603       if (file(getdownLauncher).getName() != getdown_launcher) {
1604         rename(file(getdownLauncher).getName(), getdown_launcher)
1605       }
1606       into getdownFilesDir
1607     }
1608
1609     copy {
1610       from getdownResourceDir
1611       into "${getdownFilesDir}/${getdown_resource_dir}"
1612     }
1613   }
1614
1615   if (buildDist) {
1616     inputs.dir("${jalviewDir}/${package_dir}")
1617   }
1618   outputs.dir(getdownWebsiteDir)
1619   outputs.dir(getdownFilesDir)
1620 }
1621
1622
1623 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
1624 task getdownDigestDir(type: JavaExec) {
1625   group "Help"
1626   description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
1627
1628   def digestDirPropertyName = "DIGESTDIR"
1629   doFirst {
1630     classpath = files(getdownLauncher)
1631     def digestDir = findProperty(digestDirPropertyName)
1632     if (digestDir == null) {
1633       throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
1634     }
1635     args digestDir
1636   }
1637   main = "com.threerings.getdown.tools.Digester"
1638 }
1639
1640
1641 task getdownDigest(type: JavaExec) {
1642   group = "distribution"
1643   description = "Digest the getdown website folder"
1644   dependsOn getdownWebsite
1645   doFirst {
1646     classpath = files(getdownLauncher)
1647   }
1648   main = "com.threerings.getdown.tools.Digester"
1649   args getdownWebsiteDir
1650   inputs.dir(getdownWebsiteDir)
1651   outputs.file("${getdownWebsiteDir}/digest2.txt")
1652 }
1653
1654
1655 task getdown() {
1656   group = "distribution"
1657   description = "Create the minimal and full getdown app folder for installers and website and create digest file"
1658   dependsOn getdownDigest
1659   doLast {
1660     if (reportRsyncCommand) {
1661       def fromDir = getdownWebsiteDir + (getdownWebsiteDir.endsWith('/')?'':'/')
1662       def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
1663       println "LIKELY RSYNC COMMAND:"
1664       println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
1665       if (RUNRSYNC == "true") {
1666         exec {
1667           commandLine "mkdir", "-p", toDir
1668         }
1669         exec {
1670           commandLine "rsync", "-avh", "--delete", fromDir, toDir
1671         }
1672       }
1673     }
1674   }
1675 }
1676
1677
1678 tasks.withType(JavaCompile) {
1679         options.encoding = 'UTF-8'
1680 }
1681
1682
1683 clean {
1684   doFirst {
1685     delete getdownWebsiteDir
1686     delete getdownFilesDir
1687   }
1688 }
1689
1690
1691 install4j {
1692   if (file(install4jHomeDir).exists()) {
1693     // good to go!
1694   } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
1695     install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
1696   } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
1697     install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
1698   }
1699   installDir(file(install4jHomeDir))
1700
1701   mediaTypes = Arrays.asList(install4j_media_types.split(","))
1702 }
1703
1704
1705 task copyInstall4jTemplate {
1706   def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
1707   def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
1708   inputs.file(install4jTemplateFile)
1709   inputs.file(install4jFileAssociationsFile)
1710   inputs.property("CHANNEL", { CHANNEL })
1711   outputs.file(install4jConfFile)
1712
1713   doLast {
1714     def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
1715
1716     // turn off code signing if no OSX_KEYPASS
1717     if (OSX_KEYPASS == "") {
1718       install4jConfigXml.'**'.codeSigning.each { codeSigning ->
1719         codeSigning.'@macEnabled' = "false"
1720       }
1721       install4jConfigXml.'**'.windows.each { windows ->
1722         windows.'@runPostProcessor' = "false"
1723       }
1724     }
1725
1726     // turn off checksum creation for LOCAL channel
1727     def e = install4jConfigXml.application[0]
1728     if (CHANNEL == "LOCAL") {
1729       e.'@createChecksums' = "false"
1730     } else {
1731       e.'@createChecksums' = "true"
1732     }
1733
1734     // put file association actions where placeholder action is
1735     def install4jFileAssociationsText = install4jFileAssociationsFile.text
1736     def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
1737     install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
1738       if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
1739         def parent = a.parent()
1740         parent.remove(a)
1741         fileAssociationActions.each { faa ->
1742             parent.append(faa)
1743         }
1744         // don't need to continue in .any loop once replacements have been made
1745         return true
1746       }
1747     }
1748
1749     // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
1750     // NB we're deleting the /other/ one!
1751     // Also remove the examples subdir from non-release versions
1752     def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
1753     // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
1754     if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
1755       customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
1756     } else {
1757       // remove the examples subdir from Full File Set
1758       def files = install4jConfigXml.files[0]
1759       def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
1760       def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
1761       def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
1762       def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
1763       dirEntry.parent().remove(dirEntry)
1764     }
1765     install4jConfigXml.'**'.action.any { a ->
1766       if (a.'@customizedId' == customizedIdToDelete) {
1767         def parent = a.parent()
1768         parent.remove(a)
1769         return true
1770       }
1771     }
1772
1773     // remove the "Uninstall Old Jalview (optional)" symlink from DMG for non-release DS_Stores
1774     if (! (CHANNEL == "RELEASE" || CHANNEL == "TEST-RELEASE" ) ) {
1775       def symlink = install4jConfigXml.'**'.topLevelFiles.symlink.find { sl -> sl.'@name' == "Uninstall Old Jalview (optional).app" }
1776       symlink.parent().remove(symlink)
1777     }
1778
1779     // write install4j file
1780     install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
1781   }
1782 }
1783
1784
1785 clean {
1786   doFirst {
1787     delete install4jConfFile
1788   }
1789 }
1790
1791
1792 task installers(type: com.install4j.gradle.Install4jTask) {
1793   group = "distribution"
1794   description = "Create the install4j installers"
1795   dependsOn getdown
1796   dependsOn copyInstall4jTemplate
1797
1798   projectFile = install4jConfFile
1799
1800   // create an md5 for the input files to use as version for install4j conf file
1801   def digest = MessageDigest.getInstance("MD5")
1802   digest.update(
1803     (file("${install4jDir}/${install4j_template}").text + 
1804     file("${install4jDir}/${install4j_info_plist_file_associations}").text +
1805     file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
1806   def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
1807   if (filesMd5.length() >= 8) {
1808     filesMd5 = filesMd5.substring(0,8)
1809   }
1810   def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
1811   // make install4jBuildDir relative to jalviewDir
1812   def install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
1813
1814   variables = [
1815     'JALVIEW_NAME': jalview_name,
1816     'JALVIEW_APPLICATION_NAME': install4jApplicationName,
1817     'JALVIEW_DIR': "../..",
1818     'OSX_KEYSTORE': OSX_KEYSTORE,
1819     'JSIGN_SH': JSIGN_SH,
1820     'JRE_DIR': getdown_app_dir_java,
1821     'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
1822     'JALVIEW_VERSION': JALVIEW_VERSION,
1823     'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
1824     'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
1825     'JAVA_VERSION': JAVA_VERSION,
1826     'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
1827     'VERSION': JALVIEW_VERSION,
1828     'MACOS_JAVA_VM_DIR': macosJavaVMDir,
1829     'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
1830     'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
1831     'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
1832     'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
1833     'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
1834     'COPYRIGHT_MESSAGE': install4j_copyright_message,
1835     'BUNDLE_ID': install4jBundleId,
1836     'INTERNAL_ID': install4jInternalId,
1837     'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
1838     'MACOS_DS_STORE': install4jDSStore,
1839     'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
1840     'INSTALLER_NAME': install4jInstallerName,
1841     'INSTALL4J_UTILS_DIR': install4j_utils_dir,
1842     'GETDOWN_WEBSITE_DIR': getdown_website_dir,
1843     'GETDOWN_FILES_DIR': getdown_files_dir,
1844     'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
1845     'GETDOWN_DIST_DIR': getdownAppDistDir,
1846     'GETDOWN_ALT_DIR': getdown_app_dir_alt,
1847     'GETDOWN_INSTALL_DIR': getdown_install_dir,
1848     'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
1849     'BUILD_DIR': install4jBuildDir,
1850     'APPLICATION_CATEGORIES': install4j_application_categories,
1851     'APPLICATION_FOLDER': install4jApplicationFolder,
1852     'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
1853     'EXECUTABLE_NAME': install4jExecutableName,
1854     'EXTRA_SCHEME': install4jExtraScheme,
1855   ]
1856
1857   //println("INSTALL4J VARIABLES:")
1858   //variables.each{k,v->println("${k}=${v}")}
1859
1860   destination = "${jalviewDir}/${install4jBuildDir}"
1861   buildSelected = true
1862
1863   if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
1864     faster = true
1865     disableSigning = true
1866   }
1867
1868   if (OSX_KEYPASS) {
1869     macKeystorePassword = OSX_KEYPASS
1870   }
1871
1872   doFirst {
1873     println("Using projectFile "+projectFile)
1874   }
1875
1876   inputs.dir(getdownWebsiteDir)
1877   inputs.file(install4jConfFile)
1878   inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
1879   inputs.dir(macosJavaVMDir)
1880   inputs.dir(windowsJavaVMDir)
1881   outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
1882 }
1883
1884
1885 spotless {
1886   java {
1887     eclipse().configFile(eclipse_codestyle_file)
1888   }
1889 }
1890
1891
1892 task sourceDist(type: Tar) {
1893   group "distribution"
1894   description "Create a source .tar.gz file for distribution"
1895   
1896   dependsOn convertMdFiles
1897
1898   def VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
1899   def outputFileName = "${project.name}_${VERSION_UNDERSCORES}.tar.gz"
1900   archiveFileName = outputFileName
1901   
1902   compression Compression.GZIP
1903   
1904   into project.name
1905
1906   def EXCLUDE_FILES=[
1907     "build/*",
1908     "bin/*",
1909     "test-output/",
1910     "test-reports",
1911     "tests",
1912     "clover*/*",
1913     ".*",
1914     "benchmarking/*",
1915     "**/.*",
1916     "*.class",
1917     "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
1918     "*locales/**",
1919     "utils/InstallAnywhere",
1920     "**/*.log",
1921   ] 
1922   def PROCESS_FILES=[
1923     "AUTHORS",
1924     "CITATION",
1925     "FEATURETODO",
1926     "JAVA-11-README",
1927     "FEATURETODO",
1928     "LICENSE",
1929     "**/README",
1930     "RELEASE",
1931     "THIRDPARTYLIBS",
1932     "TESTNG",
1933     "build.gradle",
1934     "gradle.properties",
1935     "**/*.java",
1936     "**/*.html",
1937     "**/*.xml",
1938     "**/*.gradle",
1939     "**/*.groovy",
1940     "**/*.properties",
1941     "**/*.perl",
1942     "**/*.sh",
1943   ]
1944   def INCLUDE_FILES=[
1945     ".settings/org.eclipse.jdt.core.jalview.prefs",
1946   ]
1947
1948   from(jalviewDir) {
1949     exclude (EXCLUDE_FILES)
1950     include (PROCESS_FILES)
1951     filter(ReplaceTokens,
1952       beginToken: '$$',
1953       endToken: '$$',
1954       tokens: [
1955         'Version-Rel': JALVIEW_VERSION,
1956         'Year-Rel': getDate("yyyy")
1957       ]
1958     )
1959   }
1960   from(jalviewDir) {
1961     exclude (EXCLUDE_FILES)
1962     exclude (PROCESS_FILES)
1963     exclude ("appletlib")
1964     exclude ("**/*locales")
1965     exclude ("*locales/**")
1966     exclude ("utils/InstallAnywhere")
1967
1968     exclude (getdown_files_dir)
1969     exclude (getdown_website_dir)
1970
1971     // exluding these as not using jars as modules yet
1972     exclude ("${j11modDir}/**/*.jar")
1973   }
1974   from(jalviewDir) {
1975     include(INCLUDE_FILES)
1976   }
1977 //  from (jalviewDir) {
1978 //    // explicit includes for stuff that seemed to not get included
1979 //    include(fileTree("test/**/*."))
1980 //    exclude(EXCLUDE_FILES)
1981 //    exclude(PROCESS_FILES)
1982 //  }
1983 }
1984
1985
1986 task helppages {
1987   dependsOn copyHelp
1988   dependsOn pubhtmlhelp
1989   
1990   inputs.dir("${helpBuildDir}/${help_dir}")
1991   outputs.dir("${buildDir}/distributions/${help_dir}")
1992 }
1993
1994
1995 task j2sSetHeadlessBuild {
1996   doFirst {
1997     IN_ECLIPSE = false
1998   }
1999 }
2000
2001
2002 task jalviewjsSetEclipseWorkspace {
2003   def propKey = "jalviewjs_eclipse_workspace"
2004   def propVal = null
2005   if (project.hasProperty(propKey)) {
2006     propVal = project.getProperty(propKey)
2007     if (propVal.startsWith("~/")) {
2008       propVal = System.getProperty("user.home") + propVal.substring(1)
2009     }
2010   }
2011   def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2012   def propsFile = file(propsFileName)
2013   def eclipseWsDir = propVal
2014   def props = new Properties()
2015
2016   def writeProps = true
2017   if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2018     def ins = new FileInputStream(propsFileName)
2019     props.load(ins)
2020     ins.close()
2021     if (props.getProperty(propKey, null) != null) {
2022       eclipseWsDir = props.getProperty(propKey)
2023       writeProps = false
2024     }
2025   }
2026
2027   if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2028     def tempDir = File.createTempDir()
2029     eclipseWsDir = tempDir.getAbsolutePath()
2030     writeProps = true
2031   }
2032   eclipseWorkspace = file(eclipseWsDir)
2033
2034   doFirst {
2035     // do not run a headless transpile when we claim to be in Eclipse
2036     if (IN_ECLIPSE) {
2037       println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2038       throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2039     } else {
2040       println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2041     }
2042
2043     if (writeProps) {
2044       props.setProperty(propKey, eclipseWsDir)
2045       propsFile.parentFile.mkdirs()
2046       def bytes = new ByteArrayOutputStream()
2047       props.store(bytes, null)
2048       def propertiesString = bytes.toString()
2049       propsFile.text = propertiesString
2050       print("NEW ")
2051     } else {
2052       print("EXISTING ")
2053     }
2054
2055     println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2056   }
2057
2058   //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2059   outputs.file(propsFileName)
2060   outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2061 }
2062
2063
2064 task jalviewjsEclipsePaths {
2065   def eclipseProduct
2066
2067   def eclipseRoot = jalviewjs_eclipse_root
2068   if (eclipseRoot.startsWith("~/")) {
2069     eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2070   }
2071   if (OperatingSystem.current().isMacOsX()) {
2072     eclipseRoot += "/Eclipse.app"
2073     eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2074     eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2075   } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2076     if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2077       eclipseRoot += "/eclipse"
2078     }
2079     eclipseBinary = "${eclipseRoot}/eclipse.exe"
2080     eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2081   } else { // linux or unix
2082     if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2083       eclipseRoot += "/eclipse"
2084 println("eclipseDir exists")
2085     }
2086     eclipseBinary = "${eclipseRoot}/eclipse"
2087     eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2088   }
2089
2090   eclipseVersion = "4.13" // default
2091   def assumedVersion = true
2092   if (file(eclipseProduct).exists()) {
2093     def fis = new FileInputStream(eclipseProduct)
2094     def props = new Properties()
2095     props.load(fis)
2096     eclipseVersion = props.getProperty("version")
2097     fis.close()
2098     assumedVersion = false
2099   }
2100   
2101   def propKey = "eclipse_debug"
2102   eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2103
2104   doFirst {
2105     // do not run a headless transpile when we claim to be in Eclipse
2106     if (IN_ECLIPSE) {
2107       println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2108       throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2109     } else {
2110       println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2111     }
2112
2113     if (!assumedVersion) {
2114       println("ECLIPSE VERSION=${eclipseVersion}")
2115     }
2116   }
2117 }
2118
2119
2120 task printProperties {
2121   group "Debug"
2122   description "Output to console all System.properties"
2123   doFirst {
2124     System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2125   }
2126 }
2127
2128
2129 task eclipseSetup {
2130   dependsOn eclipseProject
2131   dependsOn eclipseClasspath
2132   dependsOn eclipseJdt
2133 }
2134
2135
2136 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2137 task jalviewjsEclipseCopyDropins(type: Copy) {
2138   dependsOn jalviewjsEclipsePaths
2139
2140   def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2141   inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2142   def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2143
2144   from inputFiles
2145   into outputDir
2146 }
2147
2148
2149 // this eclipse -clean doesn't actually work
2150 task jalviewjsCleanEclipse(type: Exec) {
2151   dependsOn eclipseSetup
2152   dependsOn jalviewjsEclipsePaths
2153   dependsOn jalviewjsEclipseCopyDropins
2154
2155   executable(eclipseBinary)
2156   args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2157   if (eclipseDebug) {
2158     args += "-debug"
2159   }
2160   args += "-l"
2161
2162   def inputString = """exit
2163 y
2164 """
2165   def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2166   standardInput = inputByteStream
2167 }
2168
2169 /* not really working yet
2170 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2171 */
2172
2173
2174 task jalviewjsTransferUnzipSwingJs {
2175   def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2176
2177   doLast {
2178     copy {
2179       from zipTree(file_zip)
2180       into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2181     }
2182   }
2183
2184   inputs.file file_zip
2185   outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2186 }
2187
2188
2189 task jalviewjsTransferUnzipLib {
2190   def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2191
2192   doLast {
2193     zipFiles.each { file_zip -> 
2194       copy {
2195         from zipTree(file_zip)
2196         into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2197       }
2198     }
2199   }
2200
2201   inputs.files zipFiles
2202   outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2203 }
2204
2205
2206 task jalviewjsTransferUnzipAllLibs {
2207   dependsOn jalviewjsTransferUnzipSwingJs
2208   dependsOn jalviewjsTransferUnzipLib
2209 }
2210
2211
2212 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2213   group "JalviewJS"
2214   description "Create the .j2s file from the j2s.* properties"
2215
2216   jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2217   def siteDirProperty = "j2s.site.directory"
2218   def setSiteDir = false
2219   jalviewjsJ2sProps.each { prop, val ->
2220     if (val != null) {
2221       if (prop == siteDirProperty) {
2222         if (!(val.startsWith('/') || val.startsWith("file://") )) {
2223           val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
2224         }
2225         setSiteDir = true
2226       }
2227       property(prop,val)
2228     }
2229     if (!setSiteDir) { // default site location, don't override specifically set property
2230       property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
2231     }
2232   }
2233   outputFile = jalviewjsJ2sSettingsFileName
2234
2235   if (! IN_ECLIPSE) {
2236     inputs.properties(jalviewjsJ2sProps)
2237     outputs.file(jalviewjsJ2sSettingsFileName)
2238   }
2239 }
2240
2241
2242 task jalviewjsEclipseSetup {
2243   dependsOn jalviewjsEclipseCopyDropins
2244   dependsOn jalviewjsSetEclipseWorkspace
2245   dependsOn jalviewjsCreateJ2sSettings
2246 }
2247
2248
2249 task jalviewjsSyncAllLibs (type: Sync) {
2250   dependsOn jalviewjsTransferUnzipAllLibs
2251   def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
2252   inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
2253   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2254
2255   from inputFiles
2256   into outputDir
2257   def outputFiles = []
2258   rename { filename ->
2259     outputFiles += "${outputDir}/${filename}"
2260     null
2261   }
2262   preserve {
2263     include "**"
2264   }
2265   outputs.files outputFiles
2266   inputs.files inputFiles
2267 }
2268
2269
2270 task jalviewjsSyncResources (type: Sync) {
2271   def inputFiles = fileTree(dir: resourceDir)
2272   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2273
2274   from inputFiles
2275   into outputDir
2276   def outputFiles = []
2277   rename { filename ->
2278     outputFiles += "${outputDir}/${filename}"
2279     null
2280   }
2281   preserve {
2282     include "**"
2283   }
2284   outputs.files outputFiles
2285   inputs.files inputFiles
2286 }
2287
2288
2289 task jalviewjsSyncSiteResources (type: Sync) {
2290   def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
2291   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2292
2293   from inputFiles
2294   into outputDir
2295   def outputFiles = []
2296   rename { filename ->
2297     outputFiles += "${outputDir}/${filename}"
2298     null
2299   }
2300   preserve {
2301     include "**"
2302   }
2303   outputs.files outputFiles
2304   inputs.files inputFiles
2305 }
2306
2307
2308 task jalviewjsSyncBuildProperties (type: Sync) {
2309   dependsOn createBuildProperties
2310   def inputFiles = [file(buildProperties)]
2311   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2312
2313   from inputFiles
2314   into outputDir
2315   def outputFiles = []
2316   rename { filename ->
2317     outputFiles += "${outputDir}/${filename}"
2318     null
2319   }
2320   preserve {
2321     include "**"
2322   }
2323   outputs.files outputFiles
2324   inputs.files inputFiles
2325 }
2326
2327
2328 task jalviewjsProjectImport(type: Exec) {
2329   dependsOn eclipseSetup
2330   dependsOn jalviewjsEclipsePaths
2331   dependsOn jalviewjsEclipseSetup
2332
2333   doFirst {
2334     // do not run a headless import when we claim to be in Eclipse
2335     if (IN_ECLIPSE) {
2336       println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2337       throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2338     } else {
2339       println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2340     }
2341   }
2342
2343   //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
2344   def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
2345   executable(eclipseBinary)
2346   args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
2347   if (eclipseDebug) {
2348     args += "-debug"
2349   }
2350   args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2351   if (!IN_ECLIPSE) {
2352     args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2353   }
2354
2355   inputs.file("${jalviewDir}/.project")
2356   outputs.upToDateWhen { 
2357     file(projdir).exists()
2358   }
2359 }
2360
2361
2362 task jalviewjsTranspile(type: Exec) {
2363   dependsOn jalviewjsEclipseSetup 
2364   dependsOn jalviewjsProjectImport
2365   dependsOn jalviewjsEclipsePaths
2366
2367   doFirst {
2368     // do not run a headless transpile when we claim to be in Eclipse
2369     if (IN_ECLIPSE) {
2370       println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2371       throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2372     } else {
2373       println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2374     }
2375   }
2376
2377   executable(eclipseBinary)
2378   args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
2379   if (eclipseDebug) {
2380     args += "-debug"
2381   }
2382   args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2383   if (!IN_ECLIPSE) {
2384     args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2385   }
2386
2387   def stdout
2388   def stderr
2389   doFirst {
2390     stdout = new ByteArrayOutputStream()
2391     stderr = new ByteArrayOutputStream()
2392
2393     def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
2394     def logOutFile = file(logOutFileName)
2395     logOutFile.createNewFile()
2396     logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
2397 BINARY: ${eclipseBinary}
2398 VERSION: ${eclipseVersion}
2399 WORKSPACE: ${eclipseWorkspace}
2400 DEBUG: ${eclipseDebug}
2401 ----
2402 """
2403     def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2404     // combine stdout and stderr
2405     def logErrFOS = logOutFOS
2406
2407     if (jalviewjs_j2s_to_console.equals("true")) {
2408       standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2409         new org.apache.tools.ant.util.TeeOutputStream(
2410           logOutFOS,
2411           stdout),
2412         standardOutput)
2413       errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2414         new org.apache.tools.ant.util.TeeOutputStream(
2415           logErrFOS,
2416           stderr),
2417         errorOutput)
2418     } else {
2419       standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2420         logOutFOS,
2421         stdout)
2422       errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2423         logErrFOS,
2424         stderr)
2425     }
2426   }
2427
2428   doLast {
2429     if (stdout.toString().contains("Error processing ")) {
2430       // j2s did not complete transpile
2431       //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2432       if (jalviewjs_ignore_transpile_errors.equals("true")) {
2433         println("IGNORING TRANSPILE ERRORS")
2434         println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2435       } else {
2436         throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2437       }
2438     }
2439   }
2440
2441   inputs.dir("${jalviewDir}/${sourceDir}")
2442   outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
2443   outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
2444 }
2445
2446
2447 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
2448
2449   def stdout = new ByteArrayOutputStream()
2450   def stderr = new ByteArrayOutputStream()
2451
2452   def coreFile = file(jsfile)
2453   def msg = ""
2454   msg = "Creating core for ${name}...\nGenerating ${jsfile}"
2455   println(msg)
2456   logOutFile.createNewFile()
2457   logOutFile.append(msg+"\n")
2458
2459   def coreTop = file(prefixFile)
2460   def coreBottom = file(suffixFile)
2461   coreFile.getParentFile().mkdirs()
2462   coreFile.createNewFile()
2463   coreFile.write( coreTop.getText("UTF-8") )
2464   list.each {
2465     f ->
2466     if (f.exists()) {
2467       def t = f.getText("UTF-8")
2468       t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
2469       coreFile.append( t )
2470     } else {
2471       msg = "...file '"+f.getPath()+"' does not exist, skipping"
2472       println(msg)
2473       logOutFile.append(msg+"\n")
2474     }
2475   }
2476   coreFile.append( coreBottom.getText("UTF-8") )
2477
2478   msg = "Generating ${zjsfile}"
2479   println(msg)
2480   logOutFile.append(msg+"\n")
2481   def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2482   def logErrFOS = logOutFOS
2483
2484   javaexec {
2485     classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
2486     main = "com.google.javascript.jscomp.CommandLineRunner"
2487     jvmArgs = [ "-Dfile.encoding=UTF-8" ]
2488     args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
2489     maxHeapSize = "2g"
2490
2491     msg = "\nRunning '"+commandLine.join(' ')+"'\n"
2492     println(msg)
2493     logOutFile.append(msg+"\n")
2494
2495     if (logOutConsole) {
2496       standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2497         new org.apache.tools.ant.util.TeeOutputStream(
2498           logOutFOS,
2499           stdout),
2500         standardOutput)
2501         errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2502           new org.apache.tools.ant.util.TeeOutputStream(
2503             logErrFOS,
2504             stderr),
2505           errorOutput)
2506     } else {
2507       standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2508         logOutFOS,
2509         stdout)
2510         errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2511           logErrFOS,
2512           stderr)
2513     }
2514   }
2515   msg = "--"
2516   println(msg)
2517   logOutFile.append(msg+"\n")
2518 }
2519
2520
2521 task jalviewjsBuildAllCores {
2522   group "JalviewJS"
2523   description "Build the core js lib closures listed in the classlists dir"
2524   dependsOn jalviewjsTranspile
2525   dependsOn jalviewjsTransferUnzipSwingJs
2526
2527   def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
2528   def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
2529   def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
2530   def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
2531   def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
2532   def prefixFile = "${jsDir}/core/coretop2.js"
2533   def suffixFile = "${jsDir}/core/corebottom2.js"
2534
2535   inputs.file prefixFile
2536   inputs.file suffixFile
2537
2538   def classlistFiles = []
2539   // add the classlists found int the jalviewjs_classlists_dir
2540   fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
2541     file ->
2542     def name = file.getName() - ".txt"
2543     classlistFiles += [
2544       'file': file,
2545       'name': name
2546     ]
2547   }
2548
2549   // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
2550   //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
2551   classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
2552
2553   jalviewjsCoreClasslists = []
2554
2555   classlistFiles.each {
2556     hash ->
2557
2558     def file = hash['file']
2559     if (! file.exists()) {
2560       //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
2561       return false // this is a "continue" in groovy .each closure
2562     }
2563     def name = hash['name']
2564     if (name == null) {
2565       name = file.getName() - ".txt"
2566     }
2567
2568     def filelist = []
2569     file.eachLine {
2570       line ->
2571         filelist += line
2572     }
2573     def list = fileTree(dir: j2sDir, includes: filelist)
2574
2575     def jsfile = "${outputDir}/core${name}.js"
2576     def zjsfile = "${outputDir}/core${name}.z.js"
2577
2578     jalviewjsCoreClasslists += [
2579       'jsfile': jsfile,
2580       'zjsfile': zjsfile,
2581       'list': list,
2582       'name': name
2583     ]
2584
2585     inputs.file(file)
2586     inputs.files(list)
2587     outputs.file(jsfile)
2588     outputs.file(zjsfile)
2589   }
2590   
2591   // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
2592   def stevesoftClasslistName = "_stevesoft"
2593   def stevesoftClasslist = [
2594     'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
2595     'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
2596     'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
2597     'name': stevesoftClasslistName
2598   ]
2599   jalviewjsCoreClasslists += stevesoftClasslist
2600   inputs.files(stevesoftClasslist['list'])
2601   outputs.file(stevesoftClasslist['jsfile'])
2602   outputs.file(stevesoftClasslist['zjsfile'])
2603
2604   // _all core
2605   def allClasslistName = "_all"
2606   def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
2607   allJsFiles += fileTree(
2608     dir: libJ2sDir,
2609     include: "**/*.js",
2610     excludes: [
2611       // these exlusions are files that the closure-compiler produces errors for. Should fix them
2612       "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
2613       "**/org/jmol/export/JSExporter.js"
2614     ]
2615   )
2616   allJsFiles += fileTree(
2617     dir: swingJ2sDir,
2618     include: "**/*.js",
2619     excludes: [
2620       // these exlusions are files that the closure-compiler produces errors for. Should fix them
2621       "**/sun/misc/Unsafe.js",
2622       "**/swingjs/jquery/jquery-editable-select.js",
2623       "**/swingjs/jquery/j2sComboBox.js",
2624       "**/sun/misc/FloatingDecimal.js"
2625     ]
2626   )
2627   def allClasslist = [
2628     'jsfile': "${outputDir}/core${allClasslistName}.js",
2629     'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
2630     'list': allJsFiles,
2631     'name': allClasslistName
2632   ]
2633   // not including this version of "all" core at the moment
2634   //jalviewjsCoreClasslists += allClasslist
2635   inputs.files(allClasslist['list'])
2636   outputs.file(allClasslist['jsfile'])
2637   outputs.file(allClasslist['zjsfile'])
2638
2639   doFirst {
2640     def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
2641     logOutFile.getParentFile().mkdirs()
2642     logOutFile.createNewFile()
2643     logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
2644
2645     jalviewjsCoreClasslists.each {
2646       jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
2647     }
2648   }
2649
2650 }
2651
2652
2653 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
2654   copy {
2655     from inputFile
2656     into file(outputFile).getParentFile()
2657     rename { filename ->
2658       if (filename.equals(inputFile.getName())) {
2659         return file(outputFile).getName()
2660       }
2661       return null
2662     }
2663     filter(ReplaceTokens,
2664       beginToken: '_',
2665       endToken: '_',
2666       tokens: [
2667         'MAIN': '"'+main_class+'"',
2668         'CODE': "null",
2669         'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
2670         'COREKEY': jalviewjs_core_key,
2671         'CORENAME': coreName
2672       ]
2673     )
2674   }
2675 }
2676
2677
2678 task jalviewjsPublishCoreTemplates {
2679   dependsOn jalviewjsBuildAllCores
2680   def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
2681   def inputFile = file(inputFileName)
2682   def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
2683
2684   def outputFiles = []
2685   jalviewjsCoreClasslists.each { cl ->
2686     def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
2687     cl['outputfile'] = outputFile
2688     outputFiles += outputFile
2689   }
2690
2691   doFirst {
2692     jalviewjsCoreClasslists.each { cl ->
2693       jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
2694     }
2695   }
2696   inputs.file(inputFile)
2697   outputs.files(outputFiles)
2698 }
2699
2700
2701 task jalviewjsSyncCore (type: Sync) {
2702   dependsOn jalviewjsBuildAllCores
2703   dependsOn jalviewjsPublishCoreTemplates
2704   def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
2705   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2706
2707   from inputFiles
2708   into outputDir
2709   def outputFiles = []
2710   rename { filename ->
2711     outputFiles += "${outputDir}/${filename}"
2712     null
2713   }
2714   preserve {
2715     include "**"
2716   }
2717   outputs.files outputFiles
2718   inputs.files inputFiles
2719 }
2720
2721
2722 // this Copy version of TransferSiteJs will delete anything else in the target dir
2723 task jalviewjsCopyTransferSiteJs(type: Copy) {
2724   dependsOn jalviewjsTranspile
2725   from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
2726   into "${jalviewDir}/${jalviewjsSiteDir}"
2727 }
2728
2729
2730 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
2731 task jalviewjsSyncTransferSiteJs(type: Sync) {
2732   from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
2733   include "**/*.*"
2734   into "${jalviewDir}/${jalviewjsSiteDir}"
2735   preserve {
2736     include "**"
2737   }
2738 }
2739
2740
2741 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
2742 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
2743 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
2744 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
2745
2746 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
2747 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
2748 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
2749 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
2750
2751
2752 task jalviewjsPrepareSite {
2753   group "JalviewJS"
2754   description "Prepares the website folder including unzipping files and copying resources"
2755   dependsOn jalviewjsSyncAllLibs
2756   dependsOn jalviewjsSyncResources
2757   dependsOn jalviewjsSyncSiteResources
2758   dependsOn jalviewjsSyncBuildProperties
2759   dependsOn jalviewjsSyncCore
2760 }
2761
2762
2763 task jalviewjsBuildSite {
2764   group "JalviewJS"
2765   description "Builds the whole website including transpiled code"
2766   dependsOn jalviewjsCopyTransferSiteJs
2767   dependsOn jalviewjsPrepareSite
2768 }
2769
2770
2771 task cleanJalviewjsTransferSite {
2772   doFirst {
2773     delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
2774     delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2775     delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2776     delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
2777   }
2778 }
2779
2780
2781 task cleanJalviewjsSite {
2782   dependsOn cleanJalviewjsTransferSite
2783   doFirst {
2784     delete "${jalviewDir}/${jalviewjsSiteDir}"
2785   }
2786 }
2787
2788
2789 task jalviewjsSiteTar(type: Tar) {
2790   group "JalviewJS"
2791   description "Creates a tar.gz file for the website"
2792   dependsOn jalviewjsBuildSite
2793   def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
2794   archiveFileName = outputFilename
2795
2796   compression Compression.GZIP
2797
2798   from "${jalviewDir}/${jalviewjsSiteDir}"
2799   into jalviewjs_site_dir // this is inside the tar file
2800
2801   inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
2802 }
2803
2804
2805 task jalviewjsServer {
2806   group "JalviewJS"
2807   def filename = "jalviewjsTest.html"
2808   description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
2809   def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
2810   doLast {
2811
2812     SimpleHttpFileServerFactory factory = new SimpleHttpFileServerFactory()
2813     def port = Integer.valueOf(jalviewjs_server_port)
2814     def start = port
2815     def running = false
2816     def url
2817     def jalviewjsServer
2818     while(port < start+1000 && !running) {
2819       try {
2820         def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
2821         jalviewjsServer = factory.start(doc_root, port)
2822         running = true
2823         url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
2824         println("SERVER STARTED with document root ${doc_root}.")
2825         println("Go to "+url+" . Run  gradle --stop  to stop (kills all gradle daemons).")
2826         println("For debug: "+url+"?j2sdebug")
2827         println("For verbose: "+url+"?j2sverbose")
2828       } catch (Exception e) {
2829         port++;
2830       }
2831     }
2832     def htmlText = """
2833       <p><a href="${url}">JalviewJS Test. &lt;${url}&gt;</a></p>
2834       <p><a href="${url}?j2sdebug">JalviewJS Test with debug. &lt;${url}?j2sdebug&gt;</a></p>
2835       <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. &lt;${url}?j2sdebug&gt;</a></p>
2836       """
2837     jalviewjsCoreClasslists.each { cl ->
2838       def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
2839       htmlText += """
2840       <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. &lt;${urlcore}&gt;</a></p>
2841       """
2842       println("For core ${cl.name}: "+urlcore)
2843     }
2844
2845     file(htmlFile).text = htmlText
2846   }
2847
2848   outputs.file(htmlFile)
2849   outputs.upToDateWhen({false})
2850 }
2851
2852
2853 task cleanJalviewjsAll {
2854   group "JalviewJS"
2855   description "Delete all configuration and build artifacts to do with JalviewJS build"
2856   dependsOn cleanJalviewjsSite
2857   dependsOn jalviewjsEclipsePaths
2858   
2859   doFirst {
2860     delete "${jalviewDir}/${jalviewjsBuildDir}"
2861     delete "${jalviewDir}/${eclipse_bin_dir}"
2862     if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
2863       delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
2864     }
2865     delete "${jalviewDir}/${jalviewjs_j2s_settings}"
2866   }
2867
2868   outputs.upToDateWhen( { false } )
2869 }
2870
2871
2872 task jalviewjsIDE_checkJ2sPlugin {
2873   group "00 JalviewJS in Eclipse"
2874   description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
2875
2876   doFirst {
2877     def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
2878     def j2sPluginFile = file(j2sPlugin)
2879     def eclipseHome = System.properties["eclipse.home.location"]
2880     if (eclipseHome == null || ! IN_ECLIPSE) {
2881       throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
2882     }
2883     def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
2884     def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
2885     if (altPluginsDir != null && file(altPluginsDir).exists()) {
2886       eclipseJ2sPluginDirs += altPluginsDir
2887     }
2888     def foundPlugin = false
2889     def j2sPluginFileName = j2sPluginFile.getName()
2890     def eclipseJ2sPlugin
2891     def eclipseJ2sPluginFile
2892     eclipseJ2sPluginDirs.any { dir ->
2893       eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
2894       eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
2895       if (eclipseJ2sPluginFile.exists()) {
2896         foundPlugin = true
2897         return true
2898       }
2899     }
2900     if (!foundPlugin) {
2901       def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
2902       System.err.println(msg)
2903       throw new StopExecutionException(msg)
2904     }
2905
2906     def digest = MessageDigest.getInstance("MD5")
2907
2908     digest.update(j2sPluginFile.text.bytes)
2909     def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
2910
2911     digest.update(eclipseJ2sPluginFile.text.bytes)
2912     def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
2913      
2914     if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
2915       def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
2916       System.err.println(msg)
2917       throw new StopExecutionException(msg)
2918     } else {
2919       def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
2920       println(msg)
2921     }
2922   }
2923 }
2924
2925 task jalviewjsIDE_copyJ2sPlugin {
2926   group "00 JalviewJS in Eclipse"
2927   description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
2928
2929   doFirst {
2930     def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
2931     def j2sPluginFile = file(j2sPlugin)
2932     def eclipseHome = System.properties["eclipse.home.location"]
2933     if (eclipseHome == null || ! IN_ECLIPSE) {
2934       throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
2935     }
2936     def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
2937     def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
2938     def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
2939     System.err.println(msg)
2940     copy {
2941       from j2sPlugin
2942       eclipseJ2sPluginFile.getParentFile().mkdirs()
2943       into eclipseJ2sPluginFile.getParent()
2944     }
2945   }
2946 }
2947
2948
2949 task jalviewjsIDE_j2sFile {
2950   group "00 JalviewJS in Eclipse"
2951   description "Creates the .j2s file"
2952   dependsOn jalviewjsCreateJ2sSettings
2953 }
2954
2955
2956 task jalviewjsIDE_SyncCore {
2957   group "00 JalviewJS in Eclipse"
2958   description "Build the core js lib closures listed in the classlists dir and publish core html from template"
2959   dependsOn jalviewjsSyncCore
2960 }
2961
2962
2963 task jalviewjsIDE_SyncSiteAll {
2964   dependsOn jalviewjsSyncAllLibs
2965   dependsOn jalviewjsSyncResources
2966   dependsOn jalviewjsSyncSiteResources
2967   dependsOn jalviewjsSyncBuildProperties
2968 }
2969
2970
2971 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
2972
2973
2974 task jalviewjsIDE_PrepareSite {
2975   group "00 JalviewJS in Eclipse"
2976   description "Sync libs and resources to site dir, but not closure cores"
2977
2978   dependsOn jalviewjsIDE_SyncSiteAll
2979   //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
2980 }
2981
2982
2983 task jalviewjsIDE_AssembleSite {
2984   group "00 JalviewJS in Eclipse"
2985   description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
2986   dependsOn jalviewjsPrepareSite
2987 }
2988
2989
2990 task jalviewjsIDE_SiteClean {
2991   group "00 JalviewJS in Eclipse"
2992   description "Deletes the Eclipse transpiled site"
2993   dependsOn cleanJalviewjsSite
2994 }
2995
2996
2997 task jalviewjsIDE_Server {
2998   group "00 JalviewJS in Eclipse"
2999   description "Starts a webserver on localhost to test the website"
3000   dependsOn jalviewjsServer
3001 }
3002
3003
3004 // buildship runs this at import or gradle refresh
3005 task eclipseSynchronizationTask {
3006   //dependsOn eclipseSetup
3007   dependsOn createBuildProperties
3008   if (J2S_ENABLED) {
3009     dependsOn jalviewjsIDE_j2sFile
3010     dependsOn jalviewjsIDE_checkJ2sPlugin
3011     dependsOn jalviewjsIDE_PrepareSite
3012   }
3013 }
3014
3015
3016 // buildship runs this at build time or project refresh
3017 task eclipseAutoBuildTask {
3018   //dependsOn jalviewjsIDE_checkJ2sPlugin
3019   //dependsOn jalviewjsIDE_PrepareSite
3020 }
3021
3022
3023 task jalviewjs {
3024   group "JalviewJS"
3025   description "Build the site"
3026   dependsOn jalviewjsBuildSite
3027 }