JAL-3280 Test for remote release build_properties file version check
[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     /* NOT setting these properties so that getdownappbase and getdowndistdir will default to release version
1604      * getdownTextString += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}\n"
1605      * getdownTextString += "jvmarg = -Dgetdownappbase=${getdownAppBase}\n"
1606      */
1607
1608     def getdown_txt = file("${getdownWebsiteDir}/getdown.txt")
1609     getdown_txt.write(getdownTextString)
1610
1611     def getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
1612     def launchJvl = file("${getdownWebsiteDir}/${getdownLaunchJvl}")
1613     launchJvl.write("appbase=${getdownAppBase}")
1614
1615     copy {
1616       from getdownLauncher
1617       rename(file(getdownLauncher).getName(), getdown_launcher_new)
1618       into getdownWebsiteDir
1619     }
1620
1621     copy {
1622       from getdownLauncher
1623       if (file(getdownLauncher).getName() != getdown_launcher) {
1624         rename(file(getdownLauncher).getName(), getdown_launcher)
1625       }
1626       into getdownWebsiteDir
1627     }
1628
1629     if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
1630       copy {
1631         from getdown_txt
1632         from getdownLauncher
1633         from "${getdownAppDir}/${getdown_build_properties}"
1634         if (file(getdownLauncher).getName() != getdown_launcher) {
1635           rename(file(getdownLauncher).getName(), getdown_launcher)
1636         }
1637         into getdownInstallDir
1638       }
1639
1640       copy {
1641         from getdownInstallDir
1642         into getdownFilesInstallDir
1643       }
1644     }
1645
1646     copy {
1647       from getdown_txt
1648       from launchJvl
1649       from getdownLauncher
1650       from "${getdownWebsiteDir}/${getdown_build_properties}"
1651       if (file(getdownLauncher).getName() != getdown_launcher) {
1652         rename(file(getdownLauncher).getName(), getdown_launcher)
1653       }
1654       into getdownFilesDir
1655     }
1656
1657     copy {
1658       from getdownResourceDir
1659       into "${getdownFilesDir}/${getdown_resource_dir}"
1660     }
1661   }
1662
1663   if (buildDist) {
1664     inputs.dir("${jalviewDir}/${package_dir}")
1665   }
1666   outputs.dir(getdownWebsiteDir)
1667   outputs.dir(getdownFilesDir)
1668 }
1669
1670
1671 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
1672 task getdownDigestDir(type: JavaExec) {
1673   group "Help"
1674   description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
1675
1676   def digestDirPropertyName = "DIGESTDIR"
1677   doFirst {
1678     classpath = files(getdownLauncher)
1679     def digestDir = findProperty(digestDirPropertyName)
1680     if (digestDir == null) {
1681       throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
1682     }
1683     args digestDir
1684   }
1685   main = "com.threerings.getdown.tools.Digester"
1686 }
1687
1688
1689 task getdownDigest(type: JavaExec) {
1690   group = "distribution"
1691   description = "Digest the getdown website folder"
1692   dependsOn getdownWebsite
1693   doFirst {
1694     classpath = files(getdownLauncher)
1695   }
1696   main = "com.threerings.getdown.tools.Digester"
1697   args getdownWebsiteDir
1698   inputs.dir(getdownWebsiteDir)
1699   outputs.file("${getdownWebsiteDir}/digest2.txt")
1700 }
1701
1702
1703 task getdown() {
1704   group = "distribution"
1705   description = "Create the minimal and full getdown app folder for installers and website and create digest file"
1706   dependsOn getdownDigest
1707   doLast {
1708     if (reportRsyncCommand) {
1709       def fromDir = getdownWebsiteDir + (getdownWebsiteDir.endsWith('/')?'':'/')
1710       def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
1711       println "LIKELY RSYNC COMMAND:"
1712       println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
1713       if (RUNRSYNC == "true") {
1714         exec {
1715           commandLine "mkdir", "-p", toDir
1716         }
1717         exec {
1718           commandLine "rsync", "-avh", "--delete", fromDir, toDir
1719         }
1720       }
1721     }
1722   }
1723 }
1724
1725
1726 tasks.withType(JavaCompile) {
1727         options.encoding = 'UTF-8'
1728 }
1729
1730
1731 clean {
1732   doFirst {
1733     delete getdownWebsiteDir
1734     delete getdownFilesDir
1735   }
1736 }
1737
1738
1739 install4j {
1740   if (file(install4jHomeDir).exists()) {
1741     // good to go!
1742   } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
1743     install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
1744   } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
1745     install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
1746   }
1747   installDir(file(install4jHomeDir))
1748
1749   mediaTypes = Arrays.asList(install4j_media_types.split(","))
1750 }
1751
1752
1753 task copyInstall4jTemplate {
1754   def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
1755   def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
1756   inputs.file(install4jTemplateFile)
1757   inputs.file(install4jFileAssociationsFile)
1758   inputs.property("CHANNEL", { CHANNEL })
1759   outputs.file(install4jConfFile)
1760
1761   doLast {
1762     def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
1763
1764     // turn off code signing if no OSX_KEYPASS
1765     if (OSX_KEYPASS == "") {
1766       install4jConfigXml.'**'.codeSigning.each { codeSigning ->
1767         codeSigning.'@macEnabled' = "false"
1768       }
1769       install4jConfigXml.'**'.windows.each { windows ->
1770         windows.'@runPostProcessor' = "false"
1771       }
1772     }
1773
1774     // turn off checksum creation for LOCAL channel
1775     def e = install4jConfigXml.application[0]
1776     if (CHANNEL == "LOCAL") {
1777       e.'@createChecksums' = "false"
1778     } else {
1779       e.'@createChecksums' = "true"
1780     }
1781
1782     // put file association actions where placeholder action is
1783     def install4jFileAssociationsText = install4jFileAssociationsFile.text
1784     def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
1785     install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
1786       if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
1787         def parent = a.parent()
1788         parent.remove(a)
1789         fileAssociationActions.each { faa ->
1790             parent.append(faa)
1791         }
1792         // don't need to continue in .any loop once replacements have been made
1793         return true
1794       }
1795     }
1796
1797     // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
1798     // NB we're deleting the /other/ one!
1799     // Also remove the examples subdir from non-release versions
1800     def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
1801     // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
1802     if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
1803       customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
1804     } else {
1805       // remove the examples subdir from Full File Set
1806       def files = install4jConfigXml.files[0]
1807       def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
1808       def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
1809       def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
1810       def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
1811       dirEntry.parent().remove(dirEntry)
1812     }
1813     install4jConfigXml.'**'.action.any { a ->
1814       if (a.'@customizedId' == customizedIdToDelete) {
1815         def parent = a.parent()
1816         parent.remove(a)
1817         return true
1818       }
1819     }
1820
1821     // remove the "Uninstall Old Jalview (optional)" symlink from DMG for non-release DS_Stores
1822     if (! (CHANNEL == "RELEASE" || CHANNEL == "TEST-RELEASE" ) ) {
1823       def symlink = install4jConfigXml.'**'.topLevelFiles.symlink.find { sl -> sl.'@name' == "Uninstall Old Jalview (optional).app" }
1824       symlink.parent().remove(symlink)
1825     }
1826
1827     // write install4j file
1828     install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
1829   }
1830 }
1831
1832
1833 clean {
1834   doFirst {
1835     delete install4jConfFile
1836   }
1837 }
1838
1839
1840 task installers(type: com.install4j.gradle.Install4jTask) {
1841   group = "distribution"
1842   description = "Create the install4j installers"
1843   dependsOn getdown
1844   dependsOn copyInstall4jTemplate
1845
1846   projectFile = install4jConfFile
1847
1848   // create an md5 for the input files to use as version for install4j conf file
1849   def digest = MessageDigest.getInstance("MD5")
1850   digest.update(
1851     (file("${install4jDir}/${install4j_template}").text + 
1852     file("${install4jDir}/${install4j_info_plist_file_associations}").text +
1853     file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
1854   def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
1855   if (filesMd5.length() >= 8) {
1856     filesMd5 = filesMd5.substring(0,8)
1857   }
1858   def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
1859   // make install4jBuildDir relative to jalviewDir
1860   def install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
1861
1862   variables = [
1863     'JALVIEW_NAME': jalview_name,
1864     'JALVIEW_APPLICATION_NAME': install4jApplicationName,
1865     'JALVIEW_DIR': "../..",
1866     'OSX_KEYSTORE': OSX_KEYSTORE,
1867     'JSIGN_SH': JSIGN_SH,
1868     'JRE_DIR': getdown_app_dir_java,
1869     'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
1870     'JALVIEW_VERSION': JALVIEW_VERSION,
1871     'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
1872     'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
1873     'JAVA_VERSION': JAVA_VERSION,
1874     'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
1875     'VERSION': JALVIEW_VERSION,
1876     'MACOS_JAVA_VM_DIR': macosJavaVMDir,
1877     'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
1878     'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
1879     'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
1880     'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
1881     'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
1882     'COPYRIGHT_MESSAGE': install4j_copyright_message,
1883     'BUNDLE_ID': install4jBundleId,
1884     'INTERNAL_ID': install4jInternalId,
1885     'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
1886     'MACOS_DMG_DS_STORE': install4jDMGDSStore,
1887     'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
1888     'INSTALLER_NAME': install4jInstallerName,
1889     'INSTALL4J_UTILS_DIR': install4j_utils_dir,
1890     'GETDOWN_WEBSITE_DIR': getdown_website_dir,
1891     'GETDOWN_FILES_DIR': getdown_files_dir,
1892     'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
1893     'GETDOWN_DIST_DIR': getdownAppDistDir,
1894     'GETDOWN_ALT_DIR': getdown_app_dir_alt,
1895     'GETDOWN_INSTALL_DIR': getdown_install_dir,
1896     'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
1897     'BUILD_DIR': install4jBuildDir,
1898     'APPLICATION_CATEGORIES': install4j_application_categories,
1899     'APPLICATION_FOLDER': install4jApplicationFolder,
1900     'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
1901     'EXECUTABLE_NAME': install4jExecutableName,
1902     'EXTRA_SCHEME': install4jExtraScheme,
1903     'MAC_ICONS_FILE': install4jMacIconsFile,
1904     'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
1905     'PNG_ICON_FILE': install4jPngIconFile,
1906     'BACKGROUND': install4jBackground,
1907
1908   ]
1909
1910   //println("INSTALL4J VARIABLES:")
1911   //variables.each{k,v->println("${k}=${v}")}
1912
1913   destination = "${jalviewDir}/${install4jBuildDir}"
1914   buildSelected = true
1915
1916   if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
1917     faster = true
1918     disableSigning = true
1919   }
1920
1921   if (OSX_KEYPASS) {
1922     macKeystorePassword = OSX_KEYPASS
1923   }
1924
1925   doFirst {
1926     println("Using projectFile "+projectFile)
1927   }
1928
1929   inputs.dir(getdownWebsiteDir)
1930   inputs.file(install4jConfFile)
1931   inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
1932   inputs.dir(macosJavaVMDir)
1933   inputs.dir(windowsJavaVMDir)
1934   outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
1935 }
1936
1937
1938 spotless {
1939   java {
1940     eclipse().configFile(eclipse_codestyle_file)
1941   }
1942 }
1943
1944
1945 task sourceDist(type: Tar) {
1946   group "distribution"
1947   description "Create a source .tar.gz file for distribution"
1948   
1949   dependsOn convertMdFiles
1950
1951   def VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
1952   def outputFileName = "${project.name}_${VERSION_UNDERSCORES}.tar.gz"
1953   archiveFileName = outputFileName
1954   
1955   compression Compression.GZIP
1956   
1957   into project.name
1958
1959   def EXCLUDE_FILES=[
1960     "build/*",
1961     "bin/*",
1962     "test-output/",
1963     "test-reports",
1964     "tests",
1965     "clover*/*",
1966     ".*",
1967     "benchmarking/*",
1968     "**/.*",
1969     "*.class",
1970     "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
1971     "*locales/**",
1972     "utils/InstallAnywhere",
1973     "**/*.log",
1974   ] 
1975   def PROCESS_FILES=[
1976     "AUTHORS",
1977     "CITATION",
1978     "FEATURETODO",
1979     "JAVA-11-README",
1980     "FEATURETODO",
1981     "LICENSE",
1982     "**/README",
1983     "RELEASE",
1984     "THIRDPARTYLIBS",
1985     "TESTNG",
1986     "build.gradle",
1987     "gradle.properties",
1988     "**/*.java",
1989     "**/*.html",
1990     "**/*.xml",
1991     "**/*.gradle",
1992     "**/*.groovy",
1993     "**/*.properties",
1994     "**/*.perl",
1995     "**/*.sh",
1996   ]
1997   def INCLUDE_FILES=[
1998     ".settings/org.eclipse.jdt.core.jalview.prefs",
1999   ]
2000
2001   from(jalviewDir) {
2002     exclude (EXCLUDE_FILES)
2003     include (PROCESS_FILES)
2004     filter(ReplaceTokens,
2005       beginToken: '$$',
2006       endToken: '$$',
2007       tokens: [
2008         'Version-Rel': JALVIEW_VERSION,
2009         'Year-Rel': getDate("yyyy")
2010       ]
2011     )
2012   }
2013   from(jalviewDir) {
2014     exclude (EXCLUDE_FILES)
2015     exclude (PROCESS_FILES)
2016     exclude ("appletlib")
2017     exclude ("**/*locales")
2018     exclude ("*locales/**")
2019     exclude ("utils/InstallAnywhere")
2020
2021     exclude (getdown_files_dir)
2022     exclude (getdown_website_dir)
2023
2024     // exluding these as not using jars as modules yet
2025     exclude ("${j11modDir}/**/*.jar")
2026   }
2027   from(jalviewDir) {
2028     include(INCLUDE_FILES)
2029   }
2030 //  from (jalviewDir) {
2031 //    // explicit includes for stuff that seemed to not get included
2032 //    include(fileTree("test/**/*."))
2033 //    exclude(EXCLUDE_FILES)
2034 //    exclude(PROCESS_FILES)
2035 //  }
2036 }
2037
2038
2039 task helppages {
2040   dependsOn copyHelp
2041   dependsOn pubhtmlhelp
2042   
2043   inputs.dir("${helpBuildDir}/${help_dir}")
2044   outputs.dir("${buildDir}/distributions/${help_dir}")
2045 }
2046
2047
2048 task j2sSetHeadlessBuild {
2049   doFirst {
2050     IN_ECLIPSE = false
2051   }
2052 }
2053
2054
2055 task jalviewjsSetEclipseWorkspace {
2056   def propKey = "jalviewjs_eclipse_workspace"
2057   def propVal = null
2058   if (project.hasProperty(propKey)) {
2059     propVal = project.getProperty(propKey)
2060     if (propVal.startsWith("~/")) {
2061       propVal = System.getProperty("user.home") + propVal.substring(1)
2062     }
2063   }
2064   def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2065   def propsFile = file(propsFileName)
2066   def eclipseWsDir = propVal
2067   def props = new Properties()
2068
2069   def writeProps = true
2070   if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2071     def ins = new FileInputStream(propsFileName)
2072     props.load(ins)
2073     ins.close()
2074     if (props.getProperty(propKey, null) != null) {
2075       eclipseWsDir = props.getProperty(propKey)
2076       writeProps = false
2077     }
2078   }
2079
2080   if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2081     def tempDir = File.createTempDir()
2082     eclipseWsDir = tempDir.getAbsolutePath()
2083     writeProps = true
2084   }
2085   eclipseWorkspace = file(eclipseWsDir)
2086
2087   doFirst {
2088     // do not run a headless transpile when we claim to be in Eclipse
2089     if (IN_ECLIPSE) {
2090       println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2091       throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2092     } else {
2093       println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2094     }
2095
2096     if (writeProps) {
2097       props.setProperty(propKey, eclipseWsDir)
2098       propsFile.parentFile.mkdirs()
2099       def bytes = new ByteArrayOutputStream()
2100       props.store(bytes, null)
2101       def propertiesString = bytes.toString()
2102       propsFile.text = propertiesString
2103       print("NEW ")
2104     } else {
2105       print("EXISTING ")
2106     }
2107
2108     println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2109   }
2110
2111   //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2112   outputs.file(propsFileName)
2113   outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2114 }
2115
2116
2117 task jalviewjsEclipsePaths {
2118   def eclipseProduct
2119
2120   def eclipseRoot = jalviewjs_eclipse_root
2121   if (eclipseRoot.startsWith("~/")) {
2122     eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2123   }
2124   if (OperatingSystem.current().isMacOsX()) {
2125     eclipseRoot += "/Eclipse.app"
2126     eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2127     eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2128   } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2129     if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2130       eclipseRoot += "/eclipse"
2131     }
2132     eclipseBinary = "${eclipseRoot}/eclipse.exe"
2133     eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2134   } else { // linux or unix
2135     if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2136       eclipseRoot += "/eclipse"
2137 println("eclipseDir exists")
2138     }
2139     eclipseBinary = "${eclipseRoot}/eclipse"
2140     eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2141   }
2142
2143   eclipseVersion = "4.13" // default
2144   def assumedVersion = true
2145   if (file(eclipseProduct).exists()) {
2146     def fis = new FileInputStream(eclipseProduct)
2147     def props = new Properties()
2148     props.load(fis)
2149     eclipseVersion = props.getProperty("version")
2150     fis.close()
2151     assumedVersion = false
2152   }
2153   
2154   def propKey = "eclipse_debug"
2155   eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2156
2157   doFirst {
2158     // do not run a headless transpile when we claim to be in Eclipse
2159     if (IN_ECLIPSE) {
2160       println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2161       throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2162     } else {
2163       println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2164     }
2165
2166     if (!assumedVersion) {
2167       println("ECLIPSE VERSION=${eclipseVersion}")
2168     }
2169   }
2170 }
2171
2172
2173 task printProperties {
2174   group "Debug"
2175   description "Output to console all System.properties"
2176   doFirst {
2177     System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2178   }
2179 }
2180
2181
2182 task eclipseSetup {
2183   dependsOn eclipseProject
2184   dependsOn eclipseClasspath
2185   dependsOn eclipseJdt
2186 }
2187
2188
2189 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2190 task jalviewjsEclipseCopyDropins(type: Copy) {
2191   dependsOn jalviewjsEclipsePaths
2192
2193   def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2194   inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2195   def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2196
2197   from inputFiles
2198   into outputDir
2199 }
2200
2201
2202 // this eclipse -clean doesn't actually work
2203 task jalviewjsCleanEclipse(type: Exec) {
2204   dependsOn eclipseSetup
2205   dependsOn jalviewjsEclipsePaths
2206   dependsOn jalviewjsEclipseCopyDropins
2207
2208   executable(eclipseBinary)
2209   args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2210   if (eclipseDebug) {
2211     args += "-debug"
2212   }
2213   args += "-l"
2214
2215   def inputString = """exit
2216 y
2217 """
2218   def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2219   standardInput = inputByteStream
2220 }
2221
2222 /* not really working yet
2223 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2224 */
2225
2226
2227 task jalviewjsTransferUnzipSwingJs {
2228   def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2229
2230   doLast {
2231     copy {
2232       from zipTree(file_zip)
2233       into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2234     }
2235   }
2236
2237   inputs.file file_zip
2238   outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2239 }
2240
2241
2242 task jalviewjsTransferUnzipLib {
2243   def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2244
2245   doLast {
2246     zipFiles.each { file_zip -> 
2247       copy {
2248         from zipTree(file_zip)
2249         into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2250       }
2251     }
2252   }
2253
2254   inputs.files zipFiles
2255   outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2256 }
2257
2258
2259 task jalviewjsTransferUnzipAllLibs {
2260   dependsOn jalviewjsTransferUnzipSwingJs
2261   dependsOn jalviewjsTransferUnzipLib
2262 }
2263
2264
2265 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2266   group "JalviewJS"
2267   description "Create the .j2s file from the j2s.* properties"
2268
2269   jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2270   def siteDirProperty = "j2s.site.directory"
2271   def setSiteDir = false
2272   jalviewjsJ2sProps.each { prop, val ->
2273     if (val != null) {
2274       if (prop == siteDirProperty) {
2275         if (!(val.startsWith('/') || val.startsWith("file://") )) {
2276           val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
2277         }
2278         setSiteDir = true
2279       }
2280       property(prop,val)
2281     }
2282     if (!setSiteDir) { // default site location, don't override specifically set property
2283       property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
2284     }
2285   }
2286   outputFile = jalviewjsJ2sSettingsFileName
2287
2288   if (! IN_ECLIPSE) {
2289     inputs.properties(jalviewjsJ2sProps)
2290     outputs.file(jalviewjsJ2sSettingsFileName)
2291   }
2292 }
2293
2294
2295 task jalviewjsEclipseSetup {
2296   dependsOn jalviewjsEclipseCopyDropins
2297   dependsOn jalviewjsSetEclipseWorkspace
2298   dependsOn jalviewjsCreateJ2sSettings
2299 }
2300
2301
2302 task jalviewjsSyncAllLibs (type: Sync) {
2303   dependsOn jalviewjsTransferUnzipAllLibs
2304   def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
2305   inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
2306   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2307
2308   from inputFiles
2309   into outputDir
2310   def outputFiles = []
2311   rename { filename ->
2312     outputFiles += "${outputDir}/${filename}"
2313     null
2314   }
2315   preserve {
2316     include "**"
2317   }
2318   outputs.files outputFiles
2319   inputs.files inputFiles
2320 }
2321
2322
2323 task jalviewjsSyncResources (type: Sync) {
2324   dependsOn buildResources
2325
2326   def inputFiles = fileTree(dir: resourcesBuildDir)
2327   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2328
2329   from inputFiles
2330   into outputDir
2331   def outputFiles = []
2332   rename { filename ->
2333     outputFiles += "${outputDir}/${filename}"
2334     null
2335   }
2336   preserve {
2337     include "**"
2338   }
2339   outputs.files outputFiles
2340   inputs.files inputFiles
2341 }
2342
2343
2344 task jalviewjsSyncSiteResources (type: Sync) {
2345   def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
2346   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2347
2348   from inputFiles
2349   into outputDir
2350   def outputFiles = []
2351   rename { filename ->
2352     outputFiles += "${outputDir}/${filename}"
2353     null
2354   }
2355   preserve {
2356     include "**"
2357   }
2358   outputs.files outputFiles
2359   inputs.files inputFiles
2360 }
2361
2362
2363 task jalviewjsSyncBuildProperties (type: Sync) {
2364   dependsOn createBuildProperties
2365   def inputFiles = [file(buildProperties)]
2366   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
2367
2368   from inputFiles
2369   into outputDir
2370   def outputFiles = []
2371   rename { filename ->
2372     outputFiles += "${outputDir}/${filename}"
2373     null
2374   }
2375   preserve {
2376     include "**"
2377   }
2378   outputs.files outputFiles
2379   inputs.files inputFiles
2380 }
2381
2382
2383 task jalviewjsProjectImport(type: Exec) {
2384   dependsOn eclipseSetup
2385   dependsOn jalviewjsEclipsePaths
2386   dependsOn jalviewjsEclipseSetup
2387
2388   doFirst {
2389     // do not run a headless import when we claim to be in Eclipse
2390     if (IN_ECLIPSE) {
2391       println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2392       throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2393     } else {
2394       println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2395     }
2396   }
2397
2398   //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
2399   def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
2400   executable(eclipseBinary)
2401   args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
2402   if (eclipseDebug) {
2403     args += "-debug"
2404   }
2405   args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2406   if (!IN_ECLIPSE) {
2407     args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2408   }
2409
2410   inputs.file("${jalviewDir}/.project")
2411   outputs.upToDateWhen { 
2412     file(projdir).exists()
2413   }
2414 }
2415
2416
2417 task jalviewjsTranspile(type: Exec) {
2418   dependsOn jalviewjsEclipseSetup 
2419   dependsOn jalviewjsProjectImport
2420   dependsOn jalviewjsEclipsePaths
2421
2422   doFirst {
2423     // do not run a headless transpile when we claim to be in Eclipse
2424     if (IN_ECLIPSE) {
2425       println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2426       throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2427     } else {
2428       println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2429     }
2430   }
2431
2432   executable(eclipseBinary)
2433   args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
2434   if (eclipseDebug) {
2435     args += "-debug"
2436   }
2437   args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
2438   if (!IN_ECLIPSE) {
2439     args += [ "-D${j2sHeadlessBuildProperty}=true" ]
2440   }
2441
2442   def stdout
2443   def stderr
2444   doFirst {
2445     stdout = new ByteArrayOutputStream()
2446     stderr = new ByteArrayOutputStream()
2447
2448     def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
2449     def logOutFile = file(logOutFileName)
2450     logOutFile.createNewFile()
2451     logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
2452 BINARY: ${eclipseBinary}
2453 VERSION: ${eclipseVersion}
2454 WORKSPACE: ${eclipseWorkspace}
2455 DEBUG: ${eclipseDebug}
2456 ----
2457 """
2458     def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2459     // combine stdout and stderr
2460     def logErrFOS = logOutFOS
2461
2462     if (jalviewjs_j2s_to_console.equals("true")) {
2463       standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2464         new org.apache.tools.ant.util.TeeOutputStream(
2465           logOutFOS,
2466           stdout),
2467         standardOutput)
2468       errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2469         new org.apache.tools.ant.util.TeeOutputStream(
2470           logErrFOS,
2471           stderr),
2472         errorOutput)
2473     } else {
2474       standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2475         logOutFOS,
2476         stdout)
2477       errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2478         logErrFOS,
2479         stderr)
2480     }
2481   }
2482
2483   doLast {
2484     if (stdout.toString().contains("Error processing ")) {
2485       // j2s did not complete transpile
2486       //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2487       if (jalviewjs_ignore_transpile_errors.equals("true")) {
2488         println("IGNORING TRANSPILE ERRORS")
2489         println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2490       } else {
2491         throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
2492       }
2493     }
2494   }
2495
2496   inputs.dir("${jalviewDir}/${sourceDir}")
2497   outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
2498   outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
2499 }
2500
2501
2502 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
2503
2504   def stdout = new ByteArrayOutputStream()
2505   def stderr = new ByteArrayOutputStream()
2506
2507   def coreFile = file(jsfile)
2508   def msg = ""
2509   msg = "Creating core for ${name}...\nGenerating ${jsfile}"
2510   println(msg)
2511   logOutFile.createNewFile()
2512   logOutFile.append(msg+"\n")
2513
2514   def coreTop = file(prefixFile)
2515   def coreBottom = file(suffixFile)
2516   coreFile.getParentFile().mkdirs()
2517   coreFile.createNewFile()
2518   coreFile.write( coreTop.getText("UTF-8") )
2519   list.each {
2520     f ->
2521     if (f.exists()) {
2522       def t = f.getText("UTF-8")
2523       t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
2524       coreFile.append( t )
2525     } else {
2526       msg = "...file '"+f.getPath()+"' does not exist, skipping"
2527       println(msg)
2528       logOutFile.append(msg+"\n")
2529     }
2530   }
2531   coreFile.append( coreBottom.getText("UTF-8") )
2532
2533   msg = "Generating ${zjsfile}"
2534   println(msg)
2535   logOutFile.append(msg+"\n")
2536   def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
2537   def logErrFOS = logOutFOS
2538
2539   javaexec {
2540     classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
2541     main = "com.google.javascript.jscomp.CommandLineRunner"
2542     jvmArgs = [ "-Dfile.encoding=UTF-8" ]
2543     args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
2544     maxHeapSize = "2g"
2545
2546     msg = "\nRunning '"+commandLine.join(' ')+"'\n"
2547     println(msg)
2548     logOutFile.append(msg+"\n")
2549
2550     if (logOutConsole) {
2551       standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2552         new org.apache.tools.ant.util.TeeOutputStream(
2553           logOutFOS,
2554           stdout),
2555         standardOutput)
2556         errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2557           new org.apache.tools.ant.util.TeeOutputStream(
2558             logErrFOS,
2559             stderr),
2560           errorOutput)
2561     } else {
2562       standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
2563         logOutFOS,
2564         stdout)
2565         errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
2566           logErrFOS,
2567           stderr)
2568     }
2569   }
2570   msg = "--"
2571   println(msg)
2572   logOutFile.append(msg+"\n")
2573 }
2574
2575
2576 task jalviewjsBuildAllCores {
2577   group "JalviewJS"
2578   description "Build the core js lib closures listed in the classlists dir"
2579   dependsOn jalviewjsTranspile
2580   dependsOn jalviewjsTransferUnzipSwingJs
2581
2582   def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
2583   def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
2584   def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
2585   def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
2586   def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
2587   def prefixFile = "${jsDir}/core/coretop2.js"
2588   def suffixFile = "${jsDir}/core/corebottom2.js"
2589
2590   inputs.file prefixFile
2591   inputs.file suffixFile
2592
2593   def classlistFiles = []
2594   // add the classlists found int the jalviewjs_classlists_dir
2595   fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
2596     file ->
2597     def name = file.getName() - ".txt"
2598     classlistFiles += [
2599       'file': file,
2600       'name': name
2601     ]
2602   }
2603
2604   // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
2605   //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
2606   classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
2607
2608   jalviewjsCoreClasslists = []
2609
2610   classlistFiles.each {
2611     hash ->
2612
2613     def file = hash['file']
2614     if (! file.exists()) {
2615       //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
2616       return false // this is a "continue" in groovy .each closure
2617     }
2618     def name = hash['name']
2619     if (name == null) {
2620       name = file.getName() - ".txt"
2621     }
2622
2623     def filelist = []
2624     file.eachLine {
2625       line ->
2626         filelist += line
2627     }
2628     def list = fileTree(dir: j2sDir, includes: filelist)
2629
2630     def jsfile = "${outputDir}/core${name}.js"
2631     def zjsfile = "${outputDir}/core${name}.z.js"
2632
2633     jalviewjsCoreClasslists += [
2634       'jsfile': jsfile,
2635       'zjsfile': zjsfile,
2636       'list': list,
2637       'name': name
2638     ]
2639
2640     inputs.file(file)
2641     inputs.files(list)
2642     outputs.file(jsfile)
2643     outputs.file(zjsfile)
2644   }
2645   
2646   // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
2647   def stevesoftClasslistName = "_stevesoft"
2648   def stevesoftClasslist = [
2649     'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
2650     'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
2651     'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
2652     'name': stevesoftClasslistName
2653   ]
2654   jalviewjsCoreClasslists += stevesoftClasslist
2655   inputs.files(stevesoftClasslist['list'])
2656   outputs.file(stevesoftClasslist['jsfile'])
2657   outputs.file(stevesoftClasslist['zjsfile'])
2658
2659   // _all core
2660   def allClasslistName = "_all"
2661   def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
2662   allJsFiles += fileTree(
2663     dir: libJ2sDir,
2664     include: "**/*.js",
2665     excludes: [
2666       // these exlusions are files that the closure-compiler produces errors for. Should fix them
2667       "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
2668       "**/org/jmol/export/JSExporter.js"
2669     ]
2670   )
2671   allJsFiles += fileTree(
2672     dir: swingJ2sDir,
2673     include: "**/*.js",
2674     excludes: [
2675       // these exlusions are files that the closure-compiler produces errors for. Should fix them
2676       "**/sun/misc/Unsafe.js",
2677       "**/swingjs/jquery/jquery-editable-select.js",
2678       "**/swingjs/jquery/j2sComboBox.js",
2679       "**/sun/misc/FloatingDecimal.js"
2680     ]
2681   )
2682   def allClasslist = [
2683     'jsfile': "${outputDir}/core${allClasslistName}.js",
2684     'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
2685     'list': allJsFiles,
2686     'name': allClasslistName
2687   ]
2688   // not including this version of "all" core at the moment
2689   //jalviewjsCoreClasslists += allClasslist
2690   inputs.files(allClasslist['list'])
2691   outputs.file(allClasslist['jsfile'])
2692   outputs.file(allClasslist['zjsfile'])
2693
2694   doFirst {
2695     def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
2696     logOutFile.getParentFile().mkdirs()
2697     logOutFile.createNewFile()
2698     logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
2699
2700     jalviewjsCoreClasslists.each {
2701       jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
2702     }
2703   }
2704
2705 }
2706
2707
2708 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
2709   copy {
2710     from inputFile
2711     into file(outputFile).getParentFile()
2712     rename { filename ->
2713       if (filename.equals(inputFile.getName())) {
2714         return file(outputFile).getName()
2715       }
2716       return null
2717     }
2718     filter(ReplaceTokens,
2719       beginToken: '_',
2720       endToken: '_',
2721       tokens: [
2722         'MAIN': '"'+main_class+'"',
2723         'CODE': "null",
2724         'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
2725         'COREKEY': jalviewjs_core_key,
2726         'CORENAME': coreName
2727       ]
2728     )
2729   }
2730 }
2731
2732
2733 task jalviewjsPublishCoreTemplates {
2734   dependsOn jalviewjsBuildAllCores
2735   def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
2736   def inputFile = file(inputFileName)
2737   def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
2738
2739   def outputFiles = []
2740   jalviewjsCoreClasslists.each { cl ->
2741     def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
2742     cl['outputfile'] = outputFile
2743     outputFiles += outputFile
2744   }
2745
2746   doFirst {
2747     jalviewjsCoreClasslists.each { cl ->
2748       jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
2749     }
2750   }
2751   inputs.file(inputFile)
2752   outputs.files(outputFiles)
2753 }
2754
2755
2756 task jalviewjsSyncCore (type: Sync) {
2757   dependsOn jalviewjsBuildAllCores
2758   dependsOn jalviewjsPublishCoreTemplates
2759   def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
2760   def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
2761
2762   from inputFiles
2763   into outputDir
2764   def outputFiles = []
2765   rename { filename ->
2766     outputFiles += "${outputDir}/${filename}"
2767     null
2768   }
2769   preserve {
2770     include "**"
2771   }
2772   outputs.files outputFiles
2773   inputs.files inputFiles
2774 }
2775
2776
2777 // this Copy version of TransferSiteJs will delete anything else in the target dir
2778 task jalviewjsCopyTransferSiteJs(type: Copy) {
2779   dependsOn jalviewjsTranspile
2780   from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
2781   into "${jalviewDir}/${jalviewjsSiteDir}"
2782 }
2783
2784
2785 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
2786 task jalviewjsSyncTransferSiteJs(type: Sync) {
2787   from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
2788   include "**/*.*"
2789   into "${jalviewDir}/${jalviewjsSiteDir}"
2790   preserve {
2791     include "**"
2792   }
2793 }
2794
2795
2796 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
2797 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
2798 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
2799 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
2800
2801 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
2802 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
2803 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
2804 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
2805
2806
2807 task jalviewjsPrepareSite {
2808   group "JalviewJS"
2809   description "Prepares the website folder including unzipping files and copying resources"
2810   dependsOn jalviewjsSyncAllLibs
2811   dependsOn jalviewjsSyncResources
2812   dependsOn jalviewjsSyncSiteResources
2813   dependsOn jalviewjsSyncBuildProperties
2814   dependsOn jalviewjsSyncCore
2815 }
2816
2817
2818 task jalviewjsBuildSite {
2819   group "JalviewJS"
2820   description "Builds the whole website including transpiled code"
2821   dependsOn jalviewjsCopyTransferSiteJs
2822   dependsOn jalviewjsPrepareSite
2823 }
2824
2825
2826 task cleanJalviewjsTransferSite {
2827   doFirst {
2828     delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
2829     delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2830     delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2831     delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
2832   }
2833 }
2834
2835
2836 task cleanJalviewjsSite {
2837   dependsOn cleanJalviewjsTransferSite
2838   doFirst {
2839     delete "${jalviewDir}/${jalviewjsSiteDir}"
2840   }
2841 }
2842
2843
2844 task jalviewjsSiteTar(type: Tar) {
2845   group "JalviewJS"
2846   description "Creates a tar.gz file for the website"
2847   dependsOn jalviewjsBuildSite
2848   def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
2849   archiveFileName = outputFilename
2850
2851   compression Compression.GZIP
2852
2853   from "${jalviewDir}/${jalviewjsSiteDir}"
2854   into jalviewjs_site_dir // this is inside the tar file
2855
2856   inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
2857 }
2858
2859
2860 task jalviewjsServer {
2861   group "JalviewJS"
2862   def filename = "jalviewjsTest.html"
2863   description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
2864   def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
2865   doLast {
2866
2867     SimpleHttpFileServerFactory factory = new SimpleHttpFileServerFactory()
2868     def port = Integer.valueOf(jalviewjs_server_port)
2869     def start = port
2870     def running = false
2871     def url
2872     def jalviewjsServer
2873     while(port < start+1000 && !running) {
2874       try {
2875         def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
2876         jalviewjsServer = factory.start(doc_root, port)
2877         running = true
2878         url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
2879         println("SERVER STARTED with document root ${doc_root}.")
2880         println("Go to "+url+" . Run  gradle --stop  to stop (kills all gradle daemons).")
2881         println("For debug: "+url+"?j2sdebug")
2882         println("For verbose: "+url+"?j2sverbose")
2883       } catch (Exception e) {
2884         port++;
2885       }
2886     }
2887     def htmlText = """
2888       <p><a href="${url}">JalviewJS Test. &lt;${url}&gt;</a></p>
2889       <p><a href="${url}?j2sdebug">JalviewJS Test with debug. &lt;${url}?j2sdebug&gt;</a></p>
2890       <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. &lt;${url}?j2sdebug&gt;</a></p>
2891       """
2892     jalviewjsCoreClasslists.each { cl ->
2893       def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
2894       htmlText += """
2895       <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. &lt;${urlcore}&gt;</a></p>
2896       """
2897       println("For core ${cl.name}: "+urlcore)
2898     }
2899
2900     file(htmlFile).text = htmlText
2901   }
2902
2903   outputs.file(htmlFile)
2904   outputs.upToDateWhen({false})
2905 }
2906
2907
2908 task cleanJalviewjsAll {
2909   group "JalviewJS"
2910   description "Delete all configuration and build artifacts to do with JalviewJS build"
2911   dependsOn cleanJalviewjsSite
2912   dependsOn jalviewjsEclipsePaths
2913   
2914   doFirst {
2915     delete "${jalviewDir}/${jalviewjsBuildDir}"
2916     delete "${jalviewDir}/${eclipse_bin_dir}"
2917     if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
2918       delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
2919     }
2920     delete "${jalviewDir}/${jalviewjs_j2s_settings}"
2921   }
2922
2923   outputs.upToDateWhen( { false } )
2924 }
2925
2926
2927 task jalviewjsIDE_checkJ2sPlugin {
2928   group "00 JalviewJS in Eclipse"
2929   description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
2930
2931   doFirst {
2932     def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
2933     def j2sPluginFile = file(j2sPlugin)
2934     def eclipseHome = System.properties["eclipse.home.location"]
2935     if (eclipseHome == null || ! IN_ECLIPSE) {
2936       throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
2937     }
2938     def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
2939     def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
2940     if (altPluginsDir != null && file(altPluginsDir).exists()) {
2941       eclipseJ2sPluginDirs += altPluginsDir
2942     }
2943     def foundPlugin = false
2944     def j2sPluginFileName = j2sPluginFile.getName()
2945     def eclipseJ2sPlugin
2946     def eclipseJ2sPluginFile
2947     eclipseJ2sPluginDirs.any { dir ->
2948       eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
2949       eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
2950       if (eclipseJ2sPluginFile.exists()) {
2951         foundPlugin = true
2952         return true
2953       }
2954     }
2955     if (!foundPlugin) {
2956       def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
2957       System.err.println(msg)
2958       throw new StopExecutionException(msg)
2959     }
2960
2961     def digest = MessageDigest.getInstance("MD5")
2962
2963     digest.update(j2sPluginFile.text.bytes)
2964     def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
2965
2966     digest.update(eclipseJ2sPluginFile.text.bytes)
2967     def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
2968      
2969     if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
2970       def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
2971       System.err.println(msg)
2972       throw new StopExecutionException(msg)
2973     } else {
2974       def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
2975       println(msg)
2976     }
2977   }
2978 }
2979
2980 task jalviewjsIDE_copyJ2sPlugin {
2981   group "00 JalviewJS in Eclipse"
2982   description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
2983
2984   doFirst {
2985     def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
2986     def j2sPluginFile = file(j2sPlugin)
2987     def eclipseHome = System.properties["eclipse.home.location"]
2988     if (eclipseHome == null || ! IN_ECLIPSE) {
2989       throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
2990     }
2991     def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
2992     def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
2993     def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
2994     System.err.println(msg)
2995     copy {
2996       from j2sPlugin
2997       eclipseJ2sPluginFile.getParentFile().mkdirs()
2998       into eclipseJ2sPluginFile.getParent()
2999     }
3000   }
3001 }
3002
3003
3004 task jalviewjsIDE_j2sFile {
3005   group "00 JalviewJS in Eclipse"
3006   description "Creates the .j2s file"
3007   dependsOn jalviewjsCreateJ2sSettings
3008 }
3009
3010
3011 task jalviewjsIDE_SyncCore {
3012   group "00 JalviewJS in Eclipse"
3013   description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3014   dependsOn jalviewjsSyncCore
3015 }
3016
3017
3018 task jalviewjsIDE_SyncSiteAll {
3019   dependsOn jalviewjsSyncAllLibs
3020   dependsOn jalviewjsSyncResources
3021   dependsOn jalviewjsSyncSiteResources
3022   dependsOn jalviewjsSyncBuildProperties
3023 }
3024
3025
3026 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3027
3028
3029 task jalviewjsIDE_PrepareSite {
3030   group "00 JalviewJS in Eclipse"
3031   description "Sync libs and resources to site dir, but not closure cores"
3032
3033   dependsOn jalviewjsIDE_SyncSiteAll
3034   //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3035 }
3036
3037
3038 task jalviewjsIDE_AssembleSite {
3039   group "00 JalviewJS in Eclipse"
3040   description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3041   dependsOn jalviewjsPrepareSite
3042 }
3043
3044
3045 task jalviewjsIDE_SiteClean {
3046   group "00 JalviewJS in Eclipse"
3047   description "Deletes the Eclipse transpiled site"
3048   dependsOn cleanJalviewjsSite
3049 }
3050
3051
3052 task jalviewjsIDE_Server {
3053   group "00 JalviewJS in Eclipse"
3054   description "Starts a webserver on localhost to test the website"
3055   dependsOn jalviewjsServer
3056 }
3057
3058
3059 // buildship runs this at import or gradle refresh
3060 task eclipseSynchronizationTask {
3061   //dependsOn eclipseSetup
3062   dependsOn createBuildProperties
3063   if (J2S_ENABLED) {
3064     dependsOn jalviewjsIDE_j2sFile
3065     dependsOn jalviewjsIDE_checkJ2sPlugin
3066     dependsOn jalviewjsIDE_PrepareSite
3067   }
3068 }
3069
3070
3071 // buildship runs this at build time or project refresh
3072 task eclipseAutoBuildTask {
3073   //dependsOn jalviewjsIDE_checkJ2sPlugin
3074   //dependsOn jalviewjsIDE_PrepareSite
3075 }
3076
3077
3078 task jalviewjs {
3079   group "JalviewJS"
3080   description "Build the site"
3081   dependsOn jalviewjsBuildSite
3082 }