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