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