1 /* Convention for properties. Read from gradle.properties, use lower_case_underlines for property names.
2 * For properties set within build.gradle, use camelCaseNoSpace.
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 groovy.json.JsonBuilder
16 import com.vladsch.flexmark.util.ast.Node
17 import com.vladsch.flexmark.html.HtmlRenderer
18 import com.vladsch.flexmark.parser.Parser
19 import com.vladsch.flexmark.util.data.MutableDataSet
20 import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension
21 import com.vladsch.flexmark.ext.tables.TablesExtension
22 import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension
23 import com.vladsch.flexmark.ext.autolink.AutolinkExtension
24 import com.vladsch.flexmark.ext.anchorlink.AnchorLinkExtension
25 import com.vladsch.flexmark.ext.toc.TocExtension
26 import com.google.common.hash.HashCode
27 import com.google.common.hash.Hashing
28 import com.google.common.io.Files
29 import org.jsoup.Jsoup
30 import org.jsoup.nodes.Element
38 classpath "com.vladsch.flexmark:flexmark-all:0.62.0"
39 classpath "org.jsoup:jsoup:1.14.3"
48 id "com.diffplug.gradle.spotless" version "3.28.0"
49 id 'com.github.johnrengelman.shadow' version '4.0.3'
50 id 'com.install4j.gradle' version '10.0.3'
51 id 'com.dorongold.task-tree' version '2.1.0' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
52 id 'com.palantir.git-version' version '0.13.0' apply false
63 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
64 def string(Object o) {
65 return o == null ? "" : o.toString()
68 def overrideProperties(String propsFileName, boolean output = false) {
69 if (propsFileName == null) {
72 def propsFile = file(propsFileName)
73 if (propsFile != null && propsFile.exists()) {
74 println("Using properties from file '${propsFileName}'")
76 def p = new Properties()
77 def localPropsFIS = new FileInputStream(propsFile)
83 if (project.hasProperty(key)) {
84 oldval = project.findProperty(key)
85 project.setProperty(key, val)
87 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
90 ext.setProperty(key, val)
92 println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'")
96 } catch (Exception e) {
97 println("Exception reading local.properties")
104 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
105 jalviewDirRelativePath = jalviewDir
108 getdownChannelName = CHANNEL.toLowerCase()
109 // default to "default". Currently only has different cosmetics for "develop", "release", "default"
110 propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default"
111 // Import channel_properties
112 channelDir = string("${jalviewDir}/${channel_properties_dir}/${propertiesChannelName}")
113 channelGradleProperties = string("${channelDir}/channel_gradle.properties")
114 channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}")
115 overrideProperties(channelGradleProperties, false)
116 // local build environment properties
117 // can be "projectDir/local.properties"
118 overrideProperties("${projectDir}/local.properties", true)
119 // or "../projectDir_local.properties"
120 overrideProperties(projectDir.getParent() + "/" + projectDir.getName() + "_local.properties", true)
123 // Import releaseProps from the RELEASE file
124 // or a file specified via JALVIEW_RELEASE_FILE if defined
125 // Expect jalview.version and target release branch in jalview.release
126 releaseProps = new Properties();
127 def releasePropFile = findProperty("JALVIEW_RELEASE_FILE");
128 def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE";
130 (new File(releasePropFile!=null ? releasePropFile : defaultReleasePropFile)).withInputStream {
131 releaseProps.load(it)
133 } catch (Exception fileLoadError) {
134 throw new Error("Couldn't load release properties file "+(releasePropFile==null ? defaultReleasePropFile : "from custom location: releasePropFile"),fileLoadError);
137 // Set JALVIEW_VERSION if it is not already set
138 if (findProperty("JALVIEW_VERSION")==null || "".equals(JALVIEW_VERSION)) {
139 JALVIEW_VERSION = releaseProps.get("jalview.version")
141 println("JALVIEW_VERSION is set to '${JALVIEW_VERSION}'")
143 // this property set when running Eclipse headlessly
144 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
145 // this property set by Eclipse
146 eclipseApplicationProperty = string("eclipse.application")
147 // CHECK IF RUNNING FROM WITHIN ECLIPSE
148 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
149 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
150 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
151 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
152 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
156 println("WITHIN ECLIPSE IDE")
158 println("HEADLESS BUILD")
161 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
163 println("J2S ENABLED")
166 System.properties.sort { it.key }.each {
167 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
170 if (false && IN_ECLIPSE) {
171 jalviewDir = jalviewDirAbsolutePath
176 buildDate = new Date().format("yyyyMMdd")
179 bareSourceDir = string(source_dir)
180 sourceDir = string("${jalviewDir}/${bareSourceDir}")
181 resourceDir = string("${jalviewDir}/${resource_dir}")
182 bareTestSourceDir = string(test_source_dir)
183 testDir = string("${jalviewDir}/${bareTestSourceDir}")
185 classesDir = string("${jalviewDir}/${classes_dir}")
188 useClover = clover.equals("true")
189 cloverBuildDir = "${buildDir}/clover"
190 cloverInstrDir = file("${cloverBuildDir}/clover-instr")
191 cloverClassesDir = file("${cloverBuildDir}/clover-classes")
192 cloverReportDir = file("${buildDir}/reports/clover")
193 cloverTestInstrDir = file("${cloverBuildDir}/clover-test-instr")
194 cloverTestClassesDir = file("${cloverBuildDir}/clover-test-classes")
195 //cloverTestClassesDir = cloverClassesDir
196 cloverDb = string("${cloverBuildDir}/clover.db")
198 testSourceDir = useClover ? cloverTestInstrDir : testDir
199 testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}"
201 getdownChannelDir = string("${getdown_website_dir}/${propertiesChannelName}")
202 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
203 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
204 getdownFullArchiveDir = null
205 getdownTextLines = []
206 getdownLaunchJvl = null
207 getdownVersionLaunchJvl = null
209 buildProperties = null
211 // the following values might be overridden by the CHANNEL switch
212 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
213 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
214 getdownArchiveAppBase = getdown_archive_base
215 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
216 getdownAppDistDir = getdown_app_dir_alt
217 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
218 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
219 reportRsyncCommand = false
220 jvlChannelName = CHANNEL.toLowerCase()
221 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
222 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
223 install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}"
224 install4jInstallerName = "${jalview_name} Non-Release Installer"
225 install4jExecutableName = install4j_executable_name
226 install4jExtraScheme = "jalviewx"
227 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
228 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
229 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
230 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
231 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
232 install4jCheckSums = true
234 applicationName = "${jalview_name}"
238 // TODO: get bamboo build artifact URL for getdown artifacts
239 getdown_channel_base = bamboo_channelbase
240 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
241 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
242 jvlChannelName += "_${getdownChannelName}"
243 // automatically add the test group Not-bamboo for exclusion
244 if ("".equals(testng_excluded_groups)) {
245 testng_excluded_groups = "Not-bamboo"
247 install4jExtraScheme = "jalviewb"
250 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
251 getdownAppDistDir = getdown_app_dir_release
252 getdownSetAppBaseProperty = true
253 reportRsyncCommand = true
255 install4jInstallerName = "${jalview_name} Installer"
259 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
260 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
261 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
262 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
263 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
265 package_dir = string("${ARCHIVEDIR}/${package_dir}")
266 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
269 reportRsyncCommand = true
270 install4jExtraScheme = "jalviewa"
274 getdownChannelName = string("archive/${JALVIEW_VERSION}")
275 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
276 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
277 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
278 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
280 package_dir = string("${ARCHIVEDIR}/${package_dir}")
281 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
284 reportRsyncCommand = true
285 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
286 install4jSuffix = "Archive"
287 install4jExtraScheme = "jalviewa"
291 reportRsyncCommand = true
292 getdownSetAppBaseProperty = true
293 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
294 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
296 install4jSuffix = "Develop"
297 install4jExtraScheme = "jalviewd"
298 install4jInstallerName = "${jalview_name} Develop Installer"
302 reportRsyncCommand = true
303 getdownSetAppBaseProperty = true
304 // Don't ignore transpile errors for release build
305 if (jalviewjs_ignore_transpile_errors.equals("true")) {
306 jalviewjs_ignore_transpile_errors = "false"
307 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
309 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
310 install4jSuffix = "Test"
311 install4jExtraScheme = "jalviewt"
312 install4jInstallerName = "${jalview_name} Test Installer"
315 case ~/^SCRATCH(|-[-\w]*)$/:
316 getdownChannelName = CHANNEL
317 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
319 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
320 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
321 reportRsyncCommand = true
322 install4jSuffix = "Scratch"
326 if (!file("${LOCALDIR}").exists()) {
327 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
329 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
330 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
332 JALVIEW_VERSION = "TEST"
333 install4jSuffix = "Test-Local"
334 install4jExtraScheme = "jalviewt"
335 install4jInstallerName = "${jalview_name} Test Installer"
338 case [ "LOCAL", "JALVIEWJS" ]:
339 JALVIEW_VERSION = "TEST"
340 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
341 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
342 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
343 install4jExtraScheme = "jalviewl"
344 install4jCheckSums = false
347 default: // something wrong specified
348 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
352 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
353 hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_data_installers_dir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
354 hugoArchiveMdFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_version_archive_dir}/Version-${JALVIEW_VERSION_UNDERSCORES}/_index.md")
355 // override getdownAppBase if requested
356 if (findProperty("getdown_appbase_override") != null) {
357 // revert to LOCAL if empty string
358 if (string(getdown_appbase_override) == "") {
359 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
360 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
361 } else if (string(getdown_appbase_override).startsWith("file://")) {
362 getdownAppBase = string(getdown_appbase_override)
363 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
365 getdownAppBase = string(getdown_appbase_override)
367 println("Overriding getdown appbase with '${getdownAppBase}'")
369 // sanitise file name for jalview launcher file for this channel
370 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
371 // install4j application and folder names
372 if (install4jSuffix == "") {
373 install4jBundleId = "${install4j_bundle_id}"
374 install4jWinApplicationId = install4j_release_win_application_id
376 applicationName = "${jalview_name} ${install4jSuffix}"
377 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
378 // add int hash of install4jSuffix to the last part of the application_id
379 def id = install4j_release_win_application_id
380 def idsplitreverse = id.split("-").reverse()
381 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
382 install4jWinApplicationId = idsplitreverse.reverse().join("-")
384 // sanitise folder and id names
385 // install4jApplicationFolder = e.g. "Jalview Build"
386 install4jApplicationFolder = applicationName
387 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
388 .replaceAll("_+", "_") // collapse __
389 install4jInternalId = applicationName
391 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
392 .replaceAll("_+", "") // collapse __
393 //.replaceAll("_*-_*", "-") // collapse _-_
394 install4jUnixApplicationFolder = applicationName
396 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
397 .replaceAll("_+", "_") // collapse __
398 .replaceAll("_*-_*", "-") // collapse _-_
401 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
402 getdownAppDir = string("${getdownAppBaseDir}/${getdownAppDistDir}")
403 //getdownJ11libDir = "${getdownAppBaseDir}/${getdown_j11lib_dir}"
404 getdownResourceDir = string("${getdownAppBaseDir}/${getdown_resource_dir}")
405 getdownInstallDir = string("${getdownAppBaseDir}/${getdown_install_dir}")
406 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
407 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
408 /* compile without modules -- using classpath libraries
409 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
410 modules_runtimeClasspath = modules_compileClasspath
416 apply plugin: "com.palantir.git-version"
417 def details = versionDetails()
418 gitHash = details.gitHash
419 gitBranch = details.branchName
420 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
421 println("Not in a git repository. Using git values from RELEASE properties file.")
422 gitHash = releaseProps.getProperty("git.hash")
423 gitBranch = releaseProps.getProperty("git.branch")
424 } catch(java.lang.RuntimeException e1) {
425 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
428 println("Using a ${CHANNEL} profile.")
430 additional_compiler_args = []
431 // configure classpath/args for j8/j11 compilation
432 if (JAVA_VERSION.equals("1.8")) {
433 JAVA_INTEGER_VERSION = string("8")
436 libDistDir = j8libDir
437 compile_source_compatibility = 1.8
438 compile_target_compatibility = 1.8
439 // these are getdown.txt properties defined dependent on the JAVA_VERSION
440 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
441 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
442 // this property is assigned below and expanded to multiple lines in the getdown task
443 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
444 // this property is for the Java library used in eclipse
445 eclipseJavaRuntimeName = string("JavaSE-1.8")
446 } else if (JAVA_VERSION.equals("11")) {
447 JAVA_INTEGER_VERSION = string("11")
449 libDistDir = j11libDir
450 compile_source_compatibility = 11
451 compile_target_compatibility = 11
452 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
453 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
454 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
455 eclipseJavaRuntimeName = string("JavaSE-11")
456 /* compile without modules -- using classpath libraries
457 additional_compiler_args += [
458 '--module-path', modules_compileClasspath.asPath,
459 '--add-modules', j11modules
462 } else if (JAVA_VERSION.equals("17")) {
463 JAVA_INTEGER_VERSION = string("17")
465 libDistDir = j17libDir
466 compile_source_compatibility = 17
467 compile_target_compatibility = 17
468 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
469 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
470 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
471 eclipseJavaRuntimeName = string("JavaSE-17")
472 /* compile without modules -- using classpath libraries
473 additional_compiler_args += [
474 '--module-path', modules_compileClasspath.asPath,
475 '--add-modules', j11modules
479 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
484 JAVA_MIN_VERSION = JAVA_VERSION
485 JAVA_MAX_VERSION = JAVA_VERSION
486 jreInstallsDir = string(jre_installs_dir)
487 if (jreInstallsDir.startsWith("~/")) {
488 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
490 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
491 install4jConfFileName = string("jalview-install4j-conf.install4j")
492 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
493 install4jHomeDir = install4j_home_dir
494 if (install4jHomeDir.startsWith("~/")) {
495 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
498 resourceBuildDir = string("${buildDir}/resources")
499 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
500 helpBuildDir = string("${resourceBuildDir}/help_build")
501 docBuildDir = string("${resourceBuildDir}/doc_build")
503 if (buildProperties == null) {
504 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
506 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
507 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
508 helpSourceDir = string("${helpParentDir}/${help_dir}")
509 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
512 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
513 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
514 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
516 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
518 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
520 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
521 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
522 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
523 jalviewjsJalviewCoreHtmlFile = string("")
524 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
525 jalviewjsCoreClasslists = []
526 jalviewjsJalviewTemplateName = string(jalviewjs_name)
527 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
528 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
529 jalviewjsJ2sProps = null
530 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
532 eclipseWorkspace = null
533 eclipseBinary = string("")
534 eclipseVersion = string("")
544 outputDir = file(classesDir)
548 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
551 compileClasspath = files(sourceSets.main.java.outputDir)
552 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
554 runtimeClasspath = compileClasspath
555 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
560 srcDirs cloverInstrDir
561 outputDir = cloverClassesDir
565 srcDirs = sourceSets.main.resources.srcDirs
568 compileClasspath = files( sourceSets.clover.java.outputDir )
569 //compileClasspath += files( testClassesDir )
570 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
571 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
572 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
574 runtimeClasspath = compileClasspath
579 srcDirs testSourceDir
580 outputDir = file(testClassesDir)
584 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
587 compileClasspath = files( sourceSets.test.java.outputDir )
588 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
589 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
591 runtimeClasspath = compileClasspath
592 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
598 // eclipse project and settings files creation, also used by buildship
601 name = eclipse_project_name
603 natures 'org.eclipse.jdt.core.javanature',
604 'org.eclipse.jdt.groovy.core.groovyNature',
605 'org.eclipse.buildship.core.gradleprojectnature'
607 buildCommand 'org.eclipse.jdt.core.javabuilder'
608 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
612 //defaultOutputDir = sourceSets.main.java.outputDir
613 configurations.each{ c->
614 if (c.isCanBeResolved()) {
615 minusConfigurations += [c]
619 plusConfigurations = [ ]
623 def removeTheseToo = []
624 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
625 cp.entries.each { entry ->
626 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
627 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
628 // we add the resources and help/help dirs in as libs afterwards (see below)
629 if (entry.kind == 'src') {
630 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
631 removeTheseToo += entry
633 alreadyAddedSrcPath.putAt(entry.path, true)
638 cp.entries.removeAll(removeTheseToo)
640 //cp.entries += new Output("${eclipse_bin_dir}/main")
641 if (file(helpParentDir).isDirectory()) {
642 cp.entries += new Library(fileReference(helpParentDir))
644 if (file(resourceDir).isDirectory()) {
645 cp.entries += new Library(fileReference(resourceDir))
648 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
650 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
651 //don't want to add outputDir as eclipse is using its own output dir in bin/main
652 if (it.isDirectory() || ! it.exists()) {
653 // don't add dirs to classpath, especially if they don't exist
654 return false // groovy "continue" in .any closure
656 def itPath = it.toString()
657 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
658 // make relative path
659 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
661 if (alreadyAddedLibPath.get(itPath)) {
662 //println("Not adding duplicate entry "+itPath)
664 //println("Adding entry "+itPath)
665 cp.entries += new Library(fileReference(itPath))
666 alreadyAddedLibPath.put(itPath, true)
670 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
671 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
672 if (it.isDirectory() || ! it.exists()) {
673 // don't add dirs to classpath
674 return false // groovy "continue" in .any closure
677 def itPath = it.toString()
678 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
679 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
681 if (alreadyAddedLibPath.get(itPath)) {
684 def lib = new Library(fileReference(itPath))
685 lib.entryAttributes["test"] = "true"
687 alreadyAddedLibPath.put(itPath, true)
695 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
700 // for the IDE, use java 11 compatibility
701 sourceCompatibility = compile_source_compatibility
702 targetCompatibility = compile_target_compatibility
703 javaRuntimeName = eclipseJavaRuntimeName
705 // add in jalview project specific properties/preferences into eclipse core preferences
707 withProperties { props ->
708 def jalview_prefs = new Properties()
709 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
710 jalview_prefs.load(ins)
712 jalview_prefs.forEach { t, v ->
713 if (props.getAt(t) == null) {
717 // codestyle file -- overrides previous formatter prefs
718 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
719 if (csFile.exists()) {
720 XmlParser parser = new XmlParser()
721 def profiles = parser.parse(csFile)
722 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
723 if (profile != null) {
724 profile.'setting'.each { s ->
726 def value = s.'@value'
727 if (id != null && value != null) {
728 props.putAt(id, value)
739 // Don't want these to be activated if in headless build
740 synchronizationTasks "eclipseSynchronizationTask"
741 //autoBuildTasks "eclipseAutoBuildTask"
747 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
748 // Class to allow updating arbitrary properties files
749 class PropertiesFile extends PropertiesPersistableConfigurationObject {
750 public PropertiesFile(PropertiesTransformer t) { super(t); }
751 @Override protected void load(Properties properties) { }
752 @Override protected void store(Properties properties) { }
753 @Override protected String getDefaultResourceName() { return ""; }
754 // This is necessary, because PropertiesPersistableConfigurationObject fails
755 // if no default properties file exists.
756 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
759 // Task to update arbitrary properties files (set outputFile)
760 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
761 private final PropertiesFileContentMerger file;
762 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
763 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
764 protected void configure(PropertiesFile props) {
765 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
767 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
770 task eclipseUIPreferences(type: PropertiesFileTask) {
771 description = "Generate Eclipse additional settings"
772 def filename = "org.eclipse.jdt.ui.prefs"
773 outputFile = "$projectDir/.settings/${filename}" as File
776 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
781 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
782 description = "Generate Eclipse additional settings"
783 def filename = "org.eclipse.jdt.groovy.core.prefs"
784 outputFile = "$projectDir/.settings/${filename}" as File
787 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
792 task eclipseAllPreferences {
794 dependsOn eclipseUIPreferences
795 dependsOn eclipseGroovyCorePreferences
798 eclipseUIPreferences.mustRunAfter eclipseJdt
799 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
801 /* end of eclipse preferences hack */
809 delete cloverBuildDir
810 delete cloverReportDir
815 task cloverInstrJava(type: JavaExec) {
816 group = "Verification"
817 description = "Create clover instrumented source java files"
819 dependsOn cleanClover
821 inputs.files(sourceSets.main.allJava)
822 outputs.dir(cloverInstrDir)
824 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
825 classpath = sourceSets.clover.compileClasspath
826 main = "com.atlassian.clover.CloverInstr"
834 cloverInstrDir.getPath(),
836 def srcFiles = sourceSets.main.allJava.files
839 { file -> file.absolutePath }
842 args argsList.toArray()
845 delete cloverInstrDir
846 println("Clover: About to instrument "+srcFiles.size() +" files")
851 task cloverInstrTests(type: JavaExec) {
852 group = "Verification"
853 description = "Create clover instrumented source test files"
855 dependsOn cleanClover
857 inputs.files(testDir)
858 outputs.dir(cloverTestInstrDir)
860 classpath = sourceSets.clover.compileClasspath
861 main = "com.atlassian.clover.CloverInstr"
871 cloverTestInstrDir.getPath(),
873 args argsList.toArray()
876 delete cloverTestInstrDir
877 println("Clover: About to instrument test files")
883 group = "Verification"
884 description = "Create clover instrumented all source files"
886 dependsOn cloverInstrJava
887 dependsOn cloverInstrTests
891 cloverClasses.dependsOn cloverInstr
894 task cloverConsoleReport(type: JavaExec) {
895 group = "Verification"
896 description = "Creates clover console report"
899 file(cloverDb).exists()
902 inputs.dir cloverClassesDir
904 classpath = sourceSets.clover.runtimeClasspath
905 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
907 if (cloverreport_mem.length() > 0) {
908 maxHeapSize = cloverreport_mem
910 if (cloverreport_jvmargs.length() > 0) {
911 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
921 args argsList.toArray()
925 task cloverHtmlReport(type: JavaExec) {
926 group = "Verification"
927 description = "Creates clover HTML report"
930 file(cloverDb).exists()
933 def cloverHtmlDir = cloverReportDir
934 inputs.dir cloverClassesDir
935 outputs.dir cloverHtmlDir
937 classpath = sourceSets.clover.runtimeClasspath
938 main = "com.atlassian.clover.reporters.html.HtmlReporter"
940 if (cloverreport_mem.length() > 0) {
941 maxHeapSize = cloverreport_mem
943 if (cloverreport_jvmargs.length() > 0) {
944 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
955 if (cloverreport_html_options.length() > 0) {
956 argsList += cloverreport_html_options.split(" ")
959 args argsList.toArray()
963 task cloverXmlReport(type: JavaExec) {
964 group = "Verification"
965 description = "Creates clover XML report"
968 file(cloverDb).exists()
971 def cloverXmlFile = "${cloverReportDir}/clover.xml"
972 inputs.dir cloverClassesDir
973 outputs.file cloverXmlFile
975 classpath = sourceSets.clover.runtimeClasspath
976 main = "com.atlassian.clover.reporters.xml.XMLReporter"
978 if (cloverreport_mem.length() > 0) {
979 maxHeapSize = cloverreport_mem
981 if (cloverreport_jvmargs.length() > 0) {
982 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
993 if (cloverreport_xml_options.length() > 0) {
994 argsList += cloverreport_xml_options.split(" ")
997 args argsList.toArray()
1002 group = "Verification"
1003 description = "Creates clover reports"
1005 dependsOn cloverXmlReport
1006 dependsOn cloverHtmlReport
1013 sourceCompatibility = compile_source_compatibility
1014 targetCompatibility = compile_target_compatibility
1015 options.compilerArgs += additional_compiler_args
1016 print ("Setting target compatibility to "+targetCompatibility+"\n")
1018 //classpath += configurations.cloverRuntime
1024 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1025 sourceCompatibility = compile_source_compatibility
1026 targetCompatibility = compile_target_compatibility
1027 options.compilerArgs = additional_compiler_args
1028 options.encoding = "UTF-8"
1030 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1037 sourceCompatibility = compile_source_compatibility
1038 targetCompatibility = compile_target_compatibility
1039 options.compilerArgs = additional_compiler_args
1041 print ("Setting target compatibility to "+targetCompatibility+"\n")
1048 delete sourceSets.main.java.outputDir
1054 dependsOn cleanClover
1056 delete sourceSets.test.java.outputDir
1061 // format is a string like date.format("dd MMMM yyyy")
1062 def getDate(format) {
1063 return date.format(format)
1067 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1068 MutableDataSet options = new MutableDataSet()
1070 def extensions = new ArrayList<>()
1071 extensions.add(AnchorLinkExtension.create())
1072 extensions.add(AutolinkExtension.create())
1073 extensions.add(StrikethroughExtension.create())
1074 extensions.add(TaskListExtension.create())
1075 extensions.add(TablesExtension.create())
1076 extensions.add(TocExtension.create())
1078 options.set(Parser.EXTENSIONS, extensions)
1080 // set GFM table parsing options
1081 options.set(TablesExtension.WITH_CAPTION, false)
1082 options.set(TablesExtension.COLUMN_SPANS, false)
1083 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1084 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1085 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1086 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1087 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1089 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1090 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1091 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1092 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1094 Parser parser = Parser.builder(options).build()
1095 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1097 mdFiles.each { mdFile ->
1098 // add table of contents
1099 def mdText = "[TOC]\n"+mdFile.text
1101 // grab the first top-level title
1103 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1104 def matcher = mdText =~ titleRegex
1105 if (matcher.size() > 0) {
1106 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1107 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1109 // or use the filename if none found
1110 if (title == null) {
1111 title = mdFile.getName()
1114 Node document = parser.parse(mdText)
1115 String htmlBody = renderer.render(document)
1116 def htmlText = '''<html>
1117 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1118 <html xmlns="http://www.w3.org/1999/xhtml">
1120 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1121 <meta http-equiv="Content-Style-Type" content="text/css" />
1122 <meta name="generator" content="flexmark" />
1124 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1126 <style type="text/css">code{white-space: pre;}</style>
1128 htmlText += ((cssFile != null) ? cssFile.text : '')
1129 htmlText += '''</head>
1132 htmlText += htmlBody
1138 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1139 def htmlFile = file(htmlFilePath)
1140 println("Creating ${htmlFilePath}")
1141 htmlFile.text = htmlText
1146 task copyDocs(type: Copy) {
1147 def inputDir = "${jalviewDir}/${doc_dir}"
1148 def outputDir = "${docBuildDir}/${doc_dir}"
1152 include('**/*.html')
1154 filter(ReplaceTokens,
1158 'Version-Rel': JALVIEW_VERSION,
1159 'Year-Rel': getDate("yyyy")
1166 exclude('**/*.html')
1171 inputs.dir(inputDir)
1172 outputs.dir(outputDir)
1176 task convertMdFiles {
1178 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1179 def cssFile = file("${jalviewDir}/${flexmark_css}")
1182 convertMdToHtml(mdFiles, cssFile)
1185 inputs.files(mdFiles)
1186 inputs.file(cssFile)
1189 mdFiles.each { mdFile ->
1190 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1191 htmlFiles.add(file(htmlFilePath))
1193 outputs.files(htmlFiles)
1197 def hugoTemplateSubstitutions(String input, Map extras=null) {
1198 def replacements = [
1199 DATE: getDate("yyyy-MM-dd"),
1200 CHANNEL: propertiesChannelName,
1201 APPLICATION_NAME: applicationName,
1203 GIT_BRANCH: gitBranch,
1204 VERSION: JALVIEW_VERSION,
1205 JAVA_VERSION: JAVA_VERSION,
1206 VERSION_UNDERSCORES: JALVIEW_VERSION_UNDERSCORES,
1211 if (extras != null) {
1212 extras.each{ k, v ->
1213 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1216 replacements.each{ k, v ->
1217 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1222 def mdFileComponents(File mdFile, def dateOnly=false) {
1225 if (mdFile.exists()) {
1226 def inFrontMatter = false
1227 def firstLine = true
1228 mdFile.eachLine { line ->
1229 if (line.matches("---")) {
1230 def prev = inFrontMatter
1231 inFrontMatter = firstLine
1232 if (inFrontMatter != prev)
1235 if (inFrontMatter) {
1237 if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
1238 map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
1239 } else if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
1240 map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
1241 } else if (m = line =~ /^channel:\s*(\S+)/) {
1242 map["channel"] = m[0][1]
1243 } else if (m = line =~ /^version:\s*(\S+)/) {
1244 map["version"] = m[0][1]
1245 } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
1246 map[ m[0][1] ] = m[0][2]
1248 if (dateOnly && map["date"] != null) {
1254 content += line+"\n"
1259 return dateOnly ? map["date"] : [map, content]
1262 task hugoTemplates {
1264 description "Create partially populated md pages for hugo website build"
1266 def hugoTemplatesDir = file("${jalviewDir}/${hugo_templates_dir}")
1267 def hugoBuildDir = "${jalviewDir}/${hugo_build_dir}"
1268 def templateFiles = fileTree(dir: hugoTemplatesDir)
1269 def releaseMdFile = file("${jalviewDir}/${releases_dir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1270 def whatsnewMdFile = file("${jalviewDir}/${whatsnew_dir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1271 def oldJvlFile = file("${jalviewDir}/${hugo_old_jvl}")
1272 def jalviewjsFile = file("${jalviewDir}/${hugo_jalviewjs}")
1275 // specific release template for version archive
1278 def givenDate = null
1279 def givenChannel = null
1280 def givenVersion = null
1281 if (CHANNEL == "RELEASE") {
1282 def (map, content) = mdFileComponents(releaseMdFile)
1283 givenDate = map.date
1284 givenChannel = map.channel
1285 givenVersion = map.version
1287 if (givenVersion != null && givenVersion != JALVIEW_VERSION) {
1288 throw new GradleException("'version' header (${givenVersion}) found in ${releaseMdFile} does not match JALVIEW_VERSION (${JALVIEW_VERSION})")
1291 if (whatsnewMdFile.exists())
1292 whatsnew = whatsnewMdFile.text
1295 def oldJvl = oldJvlFile.exists() ? oldJvlFile.collect{it} : []
1296 def jalviewjsLink = jalviewjsFile.exists() ? jalviewjsFile.collect{it} : []
1298 def changesHugo = null
1299 if (changes != null) {
1300 changesHugo = '<div class="release_notes">\n\n'
1301 def inSection = false
1302 changes.eachLine { line ->
1304 if (m = line =~ /^##([^#].*)$/) {
1306 changesHugo += "</div>\n\n"
1308 def section = m[0][1].trim()
1309 section = section.toLowerCase()
1310 section = section.replaceAll(/ +/, "_")
1311 section = section.replaceAll(/[^a-z0-9_\-]/, "")
1312 changesHugo += "<div class=\"${section}\">\n\n"
1314 } else if (m = line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
1315 def comment = m[0][2].trim()
1316 if (comment != "") {
1317 comment = comment.replaceAll('"', """)
1319 comment.eachMatch(/JAL-\d+/) { jal -> issuekeys += jal }
1320 def newline = m[0][1]
1321 if (comment.trim() != "")
1322 newline += "{{<comment>}}${comment}{{</comment>}} "
1323 newline += m[0][3].trim()
1324 if (issuekeys.size() > 0)
1325 newline += " {{< jal issue=\"${issuekeys.join(",")}\" alt=\"${comment}\" >}}"
1326 if (m[0][4] != null)
1331 changesHugo += line+"\n"
1334 changesHugo += "\n</div>\n\n"
1336 changesHugo += '</div>'
1339 templateFiles.each{ templateFile ->
1340 def newFileName = string(hugoTemplateSubstitutions(templateFile.getName()))
1341 def relPath = hugoTemplatesDir.toPath().relativize(templateFile.toPath()).getParent()
1342 def newRelPathName = hugoTemplateSubstitutions( relPath.toString() )
1344 def outPathName = string("${hugoBuildDir}/$newRelPathName")
1348 rename(templateFile.getName(), newFileName)
1352 def newFile = file("${outPathName}/${newFileName}".toString())
1353 def content = newFile.text
1354 newFile.text = hugoTemplateSubstitutions(content,
1357 CHANGES: changesHugo,
1358 DATE: givenDate == null ? "" : givenDate.format("yyyy-MM-dd"),
1359 DRAFT: givenDate == null ? "true" : "false",
1360 JALVIEWJSLINK: jalviewjsLink.contains(JALVIEW_VERSION) ? "true" : "false",
1361 JVL_HEADER: oldJvl.contains(JALVIEW_VERSION) ? "jvl: true" : ""
1368 inputs.file(oldJvlFile)
1369 inputs.dir(hugoTemplatesDir)
1370 inputs.property("JALVIEW_VERSION", { JALVIEW_VERSION })
1371 inputs.property("CHANNEL", { CHANNEL })
1374 def getMdDate(File mdFile) {
1375 return mdFileComponents(mdFile, true)
1378 def getMdSections(String content) {
1380 def sectionContent = ""
1381 def sectionName = null
1382 content.eachLine { line ->
1384 if (m = line =~ /^##([^#].*)$/) {
1385 if (sectionName != null) {
1386 sections[sectionName] = sectionContent
1390 sectionName = m[0][1].trim()
1391 sectionName = sectionName.toLowerCase()
1392 sectionName = sectionName.replaceAll(/ +/, "_")
1393 sectionName = sectionName.replaceAll(/[^a-z0-9_\-]/, "")
1394 } else if (sectionName != null) {
1395 sectionContent += line+"\n"
1398 if (sectionContent != null) {
1399 sections[sectionName] = sectionContent
1405 task copyHelp(type: Copy) {
1406 def inputDir = helpSourceDir
1407 def outputDir = "${helpBuildDir}/${help_dir}"
1411 include('**/*.html')
1415 filter(ReplaceTokens,
1419 'Version-Rel': JALVIEW_VERSION,
1420 'Year-Rel': getDate("yyyy")
1427 exclude('**/*.html')
1434 inputs.dir(inputDir)
1435 outputs.files(helpFile)
1436 outputs.dir(outputDir)
1440 task releasesTemplates {
1442 description "Recreate whatsNew.html and releases.html from markdown files and templates in help"
1446 def releasesTemplateFile = file("${jalviewDir}/${releases_template}")
1447 def whatsnewTemplateFile = file("${jalviewDir}/${whatsnew_template}")
1448 def releasesHtmlFile = file("${helpBuildDir}/${help_dir}/${releases_html}")
1449 def whatsnewHtmlFile = file("${helpBuildDir}/${help_dir}/${whatsnew_html}")
1450 def releasesMdDir = "${jalviewDir}/${releases_dir}"
1451 def whatsnewMdDir = "${jalviewDir}/${whatsnew_dir}"
1454 def releaseMdFile = file("${releasesMdDir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1455 def whatsnewMdFile = file("${whatsnewMdDir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1457 if (CHANNEL == "RELEASE") {
1458 if (!releaseMdFile.exists()) {
1459 throw new GradleException("File ${releaseMdFile} must be created for RELEASE")
1461 if (!whatsnewMdFile.exists()) {
1462 throw new GradleException("File ${whatsnewMdFile} must be created for RELEASE")
1466 def releaseFiles = fileTree(dir: releasesMdDir, include: "release-*.md")
1467 def releaseFilesDates = releaseFiles.collectEntries {
1468 [(it): getMdDate(it)]
1470 releaseFiles = releaseFiles.sort { a,b -> releaseFilesDates[a].compareTo(releaseFilesDates[b]) }
1472 def releasesTemplate = releasesTemplateFile.text
1473 def m = releasesTemplate =~ /(?s)__VERSION_LOOP_START__(.*)__VERSION_LOOP_END__/
1474 def versionTemplate = m[0][1]
1476 MutableDataSet options = new MutableDataSet()
1478 def extensions = new ArrayList<>()
1479 options.set(Parser.EXTENSIONS, extensions)
1480 options.set(Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE, true)
1482 Parser parser = Parser.builder(options).build()
1483 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1485 def actualVersions = releaseFiles.collect { rf ->
1486 def (rfMap, rfContent) = mdFileComponents(rf)
1487 return rfMap.version
1489 def versionsHtml = ""
1490 def linkedVersions = []
1491 releaseFiles.reverse().each { rFile ->
1492 def (rMap, rContent) = mdFileComponents(rFile)
1494 def versionLink = ""
1495 def partialVersion = ""
1496 def firstPart = true
1497 rMap.version.split("\\.").each { part ->
1498 def displayPart = ( firstPart ? "" : "." ) + part
1499 partialVersion += displayPart
1501 linkedVersions.contains(partialVersion)
1502 || ( actualVersions.contains(partialVersion) && partialVersion != rMap.version )
1504 versionLink += displayPart
1506 versionLink += "<a id=\"Jalview.${partialVersion}\">${displayPart}</a>"
1507 linkedVersions += partialVersion
1511 def displayDate = releaseFilesDates[rFile].format("dd/MM/yyyy")
1514 def rContentProcessed = ""
1515 rContent.eachLine { line ->
1516 if (lm = line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
1517 line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}"
1518 } else if (lm = line =~ /^###([^#]+.*)$/) {
1519 line = "_${lm[0][1].trim()}_"
1521 rContentProcessed += line + "\n"
1524 def rContentSections = getMdSections(rContentProcessed)
1525 def rVersion = versionTemplate
1526 if (rVersion != "") {
1527 def rNewFeatures = rContentSections["new_features"]
1528 def rIssuesResolved = rContentSections["issues_resolved"]
1529 Node newFeaturesNode = parser.parse(rNewFeatures)
1530 String newFeaturesHtml = renderer.render(newFeaturesNode)
1531 Node issuesResolvedNode = parser.parse(rIssuesResolved)
1532 String issuesResolvedHtml = renderer.render(issuesResolvedNode)
1533 rVersion = hugoTemplateSubstitutions(rVersion,
1535 VERSION: rMap.version,
1536 VERSION_LINK: versionLink,
1537 DISPLAY_DATE: displayDate,
1538 NEW_FEATURES: newFeaturesHtml,
1539 ISSUES_RESOLVED: issuesResolvedHtml
1542 versionsHtml += rVersion
1546 releasesTemplate = releasesTemplate.replaceAll("(?s)__VERSION_LOOP_START__.*__VERSION_LOOP_END__", versionsHtml)
1547 releasesTemplate = hugoTemplateSubstitutions(releasesTemplate)
1548 releasesHtmlFile.text = releasesTemplate
1550 if (whatsnewMdFile.exists()) {
1551 def wnDisplayDate = releaseFilesDates[releaseMdFile] != null ? releaseFilesDates[releaseMdFile].format("dd MMMM yyyy") : ""
1552 def whatsnewMd = hugoTemplateSubstitutions(whatsnewMdFile.text)
1553 Node whatsnewNode = parser.parse(whatsnewMd)
1554 String whatsnewHtml = renderer.render(whatsnewNode)
1555 whatsnewHtml = whatsnewTemplateFile.text.replaceAll("__WHATS_NEW__", whatsnewHtml)
1556 whatsnewHtmlFile.text = hugoTemplateSubstitutions(whatsnewHtml,
1558 VERSION: JALVIEW_VERSION,
1559 DISPLAY_DATE: wnDisplayDate
1562 } else if (gradle.taskGraph.hasTask(":linkCheck")) {
1563 whatsnewHtmlFile.text = "Development build " + getDate("yyyy-MM-dd HH:mm:ss")
1568 inputs.file(releasesTemplateFile)
1569 inputs.file(whatsnewTemplateFile)
1570 inputs.dir(releasesMdDir)
1571 inputs.dir(whatsnewMdDir)
1572 outputs.file(releasesHtmlFile)
1573 outputs.file(whatsnewHtmlFile)
1577 task copyResources(type: Copy) {
1579 description = "Copy (and make text substitutions in) the resources dir to the build area"
1581 def inputDir = resourceDir
1582 def outputDir = resourcesBuildDir
1586 include('**/*.html')
1588 filter(ReplaceTokens,
1592 'Version-Rel': JALVIEW_VERSION,
1593 'Year-Rel': getDate("yyyy")
1600 exclude('**/*.html')
1605 inputs.dir(inputDir)
1606 outputs.dir(outputDir)
1609 task copyChannelResources(type: Copy) {
1610 dependsOn copyResources
1612 description = "Copy the channel resources dir to the build resources area"
1614 def inputDir = "${channelDir}/${resource_dir}"
1615 def outputDir = resourcesBuildDir
1619 inputs.dir(inputDir)
1620 outputs.dir(outputDir)
1623 task createBuildProperties(type: WriteProperties) {
1624 dependsOn copyResources
1626 description = "Create the ${buildProperties} file"
1628 inputs.dir(sourceDir)
1629 inputs.dir(resourcesBuildDir)
1630 outputFile (buildProperties)
1631 // taking time specific comment out to allow better incremental builds
1632 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1633 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1634 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1635 property "VERSION", JALVIEW_VERSION
1636 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1637 property "JAVA_COMPILE_VERSION", JAVA_INTEGER_VERSION
1638 if (getdownSetAppBaseProperty) {
1639 property "GETDOWNAPPBASE", getdownAppBase
1640 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1642 outputs.file(outputFile)
1646 task buildIndices(type: JavaExec) {
1648 classpath = sourceSets.main.compileClasspath
1649 main = "com.sun.java.help.search.Indexer"
1650 workingDir = "${helpBuildDir}/${help_dir}"
1653 inputs.dir("${workingDir}/${argDir}")
1655 outputs.dir("${classesDir}/doc")
1656 outputs.dir("${classesDir}/help")
1657 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1658 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1659 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1660 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1661 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1662 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1665 task buildResources {
1666 dependsOn copyResources
1667 dependsOn copyChannelResources
1668 dependsOn createBuildProperties
1672 dependsOn buildResources
1675 dependsOn releasesTemplates
1676 dependsOn convertMdFiles
1677 dependsOn buildIndices
1681 compileJava.dependsOn prepare
1682 run.dependsOn compileJava
1683 //run.dependsOn prepare
1686 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1691 dependsOn cloverClasses
1693 dependsOn compileJava //?
1697 includeGroups testng_groups
1698 excludeGroups testng_excluded_groups
1700 useDefaultListeners=true
1703 maxHeapSize = "1024m"
1705 workingDir = jalviewDir
1706 def testLaf = project.findProperty("test_laf")
1707 if (testLaf != null) {
1708 println("Setting Test LaF to '${testLaf}'")
1709 systemProperty "laf", testLaf
1711 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1712 if (testHiDPIScale != null) {
1713 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1714 systemProperty "sun.java2d.uiScale", testHiDPIScale
1716 sourceCompatibility = compile_source_compatibility
1717 targetCompatibility = compile_target_compatibility
1718 jvmArgs += additional_compiler_args
1722 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1728 task compileLinkCheck(type: JavaCompile) {
1730 classpath = files("${jalviewDir}/${utils_dir}")
1731 destinationDir = file("${jalviewDir}/${utils_dir}")
1732 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1734 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1735 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1736 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1737 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1741 task linkCheck(type: JavaExec) {
1743 dependsOn compileLinkCheck
1745 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1746 classpath = files("${jalviewDir}/${utils_dir}")
1747 main = "HelpLinksChecker"
1748 workingDir = "${helpBuildDir}"
1749 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1751 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1752 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1755 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1759 inputs.dir(helpBuildDir)
1760 outputs.file(helpLinksCheckerOutFile)
1764 // import the pubhtmlhelp target
1765 ant.properties.basedir = "${jalviewDir}"
1766 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1767 ant.importBuild "${utils_dir}/publishHelp.xml"
1770 task cleanPackageDir(type: Delete) {
1772 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1782 attributes "Main-Class": main_class,
1783 "Permissions": "all-permissions",
1784 "Application-Name": applicationName,
1785 "Codebase": application_codebase,
1786 "Implementation-Version": JALVIEW_VERSION
1789 def outputDir = "${jalviewDir}/${package_dir}"
1790 destinationDirectory = file(outputDir)
1791 archiveFileName = rootProject.name+".jar"
1792 duplicatesStrategy "EXCLUDE"
1799 exclude "**/*.jar.*"
1801 inputs.dir(sourceSets.main.java.outputDir)
1802 sourceSets.main.resources.srcDirs.each{ dir ->
1805 outputs.file("${outputDir}/${archiveFileName}")
1809 task copyJars(type: Copy) {
1810 from fileTree(dir: classesDir, include: "**/*.jar").files
1811 into "${jalviewDir}/${package_dir}"
1815 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1816 task syncJars(type: Sync) {
1818 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1819 into "${jalviewDir}/${package_dir}"
1821 include jar.archiveFileName.getOrNull()
1828 description = "Put all required libraries in dist"
1829 // order of "cleanPackageDir", "copyJars", "jar" important!
1830 jar.mustRunAfter cleanPackageDir
1831 syncJars.mustRunAfter cleanPackageDir
1832 dependsOn cleanPackageDir
1835 outputs.dir("${jalviewDir}/${package_dir}")
1840 dependsOn cleanPackageDir
1847 group = "distribution"
1848 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1852 from ("${jalviewDir}/${libDistDir}") {
1856 attributes "Implementation-Version": JALVIEW_VERSION,
1857 "Application-Name": applicationName
1860 duplicatesStrategy "INCLUDE"
1862 mainClassName = shadow_jar_main_class
1864 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1869 task getdownWebsite() {
1870 group = "distribution"
1871 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1876 def getdownWebsiteResourceFilenames = []
1877 def getdownResourceDir = getdownResourceDir
1878 def getdownResourceFilenames = []
1881 // clean the getdown website and files dir before creating getdown folders
1882 delete getdownAppBaseDir
1883 delete getdownFilesDir
1886 from buildProperties
1887 rename(file(buildProperties).getName(), getdown_build_properties)
1890 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1893 from channelPropsFile
1894 into getdownAppBaseDir
1896 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1898 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1899 def props = project.properties.sort { it.key }
1900 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1901 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1903 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1904 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1906 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1907 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1909 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1910 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1911 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1912 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1913 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1914 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1915 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1918 props.put("getdown_txt_title", jalview_name)
1919 props.put("getdown_txt_ui.name", applicationName)
1921 // start with appbase
1922 getdownTextLines += "appbase = ${getdownAppBase}"
1923 props.each{ prop, val ->
1924 if (prop.startsWith("getdown_txt_") && val != null) {
1925 if (prop.startsWith("getdown_txt_multi_")) {
1926 def key = prop.substring(18)
1927 val.split(",").each{ v ->
1928 def line = "${key} = ${v}"
1929 getdownTextLines += line
1932 // file values rationalised
1933 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1935 if (val.indexOf('/') == 0) {
1938 } else if (val.indexOf('/') > 0) {
1939 // relative path (relative to jalviewDir)
1940 r = file( "${jalviewDir}/${val}" )
1943 val = "${getdown_resource_dir}/" + r.getName()
1944 getdownWebsiteResourceFilenames += val
1945 getdownResourceFilenames += r.getPath()
1948 if (! prop.startsWith("getdown_txt_resource")) {
1949 def line = prop.substring(12) + " = ${val}"
1950 getdownTextLines += line
1956 getdownWebsiteResourceFilenames.each{ filename ->
1957 getdownTextLines += "resource = ${filename}"
1959 getdownResourceFilenames.each{ filename ->
1962 into getdownResourceDir
1966 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1967 getdownWrapperScripts.each{ script ->
1968 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1972 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
1974 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1979 fileTree(file(package_dir)).each{ f ->
1980 if (f.isDirectory()) {
1981 def files = fileTree(dir: f, include: ["*"]).getFiles()
1983 } else if (f.exists()) {
1987 def jalviewJar = jar.archiveFileName.getOrNull()
1988 // put jalview.jar first for CLASSPATH and .properties files reasons
1989 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1990 def name = f.getName()
1991 def line = "code = ${getdownAppDistDir}/${name}"
1992 getdownTextLines += line
1999 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
2001 if (JAVA_VERSION.equals("11")) {
2002 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
2003 j11libFiles.sort().each{f ->
2004 def name = f.getName()
2005 def line = "code = ${getdown_j11lib_dir}/${name}"
2006 getdownTextLines += line
2009 into getdownJ11libDir
2015 // 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.
2016 //getdownTextLines += "class = " + file(getdownLauncher).getName()
2017 getdownTextLines += "resource = ${getdown_launcher_new}"
2018 getdownTextLines += "class = ${main_class}"
2019 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
2020 if (getdownSetAppBaseProperty) {
2021 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
2022 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
2025 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
2026 getdownTxt.write(getdownTextLines.join("\n"))
2028 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
2029 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
2030 launchJvl.write("appbase=${getdownAppBase}")
2032 // files going into the getdown website dir: getdown-launcher.jar
2034 from getdownLauncher
2035 rename(file(getdownLauncher).getName(), getdown_launcher_new)
2036 into getdownAppBaseDir
2039 // files going into the getdown website dir: getdown-launcher(-local).jar
2041 from getdownLauncher
2042 if (file(getdownLauncher).getName() != getdown_launcher) {
2043 rename(file(getdownLauncher).getName(), getdown_launcher)
2045 into getdownAppBaseDir
2048 // files going into the getdown website dir: ./install dir and files
2049 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
2052 from getdownLauncher
2053 from "${getdownAppDir}/${getdown_build_properties}"
2054 if (file(getdownLauncher).getName() != getdown_launcher) {
2055 rename(file(getdownLauncher).getName(), getdown_launcher)
2057 into getdownInstallDir
2060 // and make a copy in the getdown files dir (these are not downloaded by getdown)
2062 from getdownInstallDir
2063 into getdownFilesInstallDir
2067 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2071 from getdownLauncher
2072 from "${getdownAppBaseDir}/${getdown_build_properties}"
2073 from "${getdownAppBaseDir}/${channel_props}"
2074 if (file(getdownLauncher).getName() != getdown_launcher) {
2075 rename(file(getdownLauncher).getName(), getdown_launcher)
2077 into getdownFilesDir
2080 // and ./resource (not all downloaded by getdown)
2082 from getdownResourceDir
2083 into "${getdownFilesDir}/${getdown_resource_dir}"
2088 inputs.dir("${jalviewDir}/${package_dir}")
2090 outputs.dir(getdownAppBaseDir)
2091 outputs.dir(getdownFilesDir)
2095 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
2096 task getdownDigestDir(type: JavaExec) {
2098 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
2100 def digestDirPropertyName = "DIGESTDIR"
2102 classpath = files(getdownLauncher)
2103 def digestDir = findProperty(digestDirPropertyName)
2104 if (digestDir == null) {
2105 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
2109 main = "com.threerings.getdown.tools.Digester"
2113 task getdownDigest(type: JavaExec) {
2114 group = "distribution"
2115 description = "Digest the getdown website folder"
2116 dependsOn getdownWebsite
2118 classpath = files(getdownLauncher)
2120 main = "com.threerings.getdown.tools.Digester"
2121 args getdownAppBaseDir
2122 inputs.dir(getdownAppBaseDir)
2123 outputs.file("${getdownAppBaseDir}/digest2.txt")
2128 group = "distribution"
2129 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
2130 dependsOn getdownDigest
2132 if (reportRsyncCommand) {
2133 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
2134 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
2135 println "LIKELY RSYNC COMMAND:"
2136 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
2137 if (RUNRSYNC == "true") {
2139 commandLine "mkdir", "-p", toDir
2142 commandLine "rsync", "-avh", "--delete", fromDir, toDir
2150 task getdownArchiveBuild() {
2151 group = "distribution"
2152 description = "Put files in the archive dir to go on the website"
2154 dependsOn getdownWebsite
2156 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
2157 def vDir = "${getdownArchiveDir}/${v}"
2158 getdownFullArchiveDir = "${vDir}/getdown"
2159 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
2161 def vAltDir = "alt_${v}"
2162 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
2165 // cleanup old "old" dir
2166 delete getdownArchiveDir
2168 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
2169 getdownArchiveTxt.getParentFile().mkdirs()
2170 def getdownArchiveTextLines = []
2171 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
2175 from "${getdownAppBaseDir}/${getdownAppDistDir}"
2176 into "${getdownFullArchiveDir}/${vAltDir}"
2179 getdownTextLines.each { line ->
2180 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
2181 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
2182 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
2183 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
2184 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
2185 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
2186 // remove the existing resource = resource/ or bin/ lines
2187 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
2188 getdownArchiveTextLines += line
2192 // the resource dir -- add these files as resource lines in getdown.txt
2194 from "${archiveImagesDir}"
2195 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
2197 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
2201 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
2203 def vLaunchJvl = file(getdownVersionLaunchJvl)
2204 vLaunchJvl.getParentFile().mkdirs()
2205 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
2206 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
2207 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
2208 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
2209 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
2210 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
2212 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2214 from getdownLauncher
2215 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
2216 from "${getdownAppBaseDir}/${getdown_launcher_new}"
2217 from "${getdownAppBaseDir}/${channel_props}"
2218 if (file(getdownLauncher).getName() != getdown_launcher) {
2219 rename(file(getdownLauncher).getName(), getdown_launcher)
2221 into getdownFullArchiveDir
2227 task getdownArchiveDigest(type: JavaExec) {
2228 group = "distribution"
2229 description = "Digest the getdown archive folder"
2231 dependsOn getdownArchiveBuild
2234 classpath = files(getdownLauncher)
2235 args getdownFullArchiveDir
2237 main = "com.threerings.getdown.tools.Digester"
2238 inputs.dir(getdownFullArchiveDir)
2239 outputs.file("${getdownFullArchiveDir}/digest2.txt")
2242 task getdownArchive() {
2243 group = "distribution"
2244 description = "Build the website archive dir with getdown digest"
2246 dependsOn getdownArchiveBuild
2247 dependsOn getdownArchiveDigest
2250 tasks.withType(JavaCompile) {
2251 options.encoding = 'UTF-8'
2257 delete getdownAppBaseDir
2258 delete getdownFilesDir
2259 delete getdownArchiveDir
2265 if (file(install4jHomeDir).exists()) {
2267 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
2268 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
2269 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
2270 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
2272 installDir(file(install4jHomeDir))
2274 mediaTypes = Arrays.asList(install4j_media_types.split(","))
2278 task copyInstall4jTemplate {
2279 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
2280 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
2281 inputs.file(install4jTemplateFile)
2282 inputs.file(install4jFileAssociationsFile)
2283 inputs.property("CHANNEL", { CHANNEL })
2284 outputs.file(install4jConfFile)
2287 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
2289 // turn off code signing if no OSX_KEYPASS
2290 if (OSX_KEYPASS == "") {
2291 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
2292 codeSigning.'@macEnabled' = "false"
2294 install4jConfigXml.'**'.windows.each { windows ->
2295 windows.'@runPostProcessor' = "false"
2299 // disable install screen for OSX dmg (for 2.11.2.0)
2300 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
2301 macosArchive.attributes().remove('executeSetupApp')
2302 macosArchive.attributes().remove('setupAppId')
2305 // turn off checksum creation for LOCAL channel
2306 def e = install4jConfigXml.application[0]
2307 e.'@createChecksums' = string(install4jCheckSums)
2309 // put file association actions where placeholder action is
2310 def install4jFileAssociationsText = install4jFileAssociationsFile.text
2311 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
2312 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
2313 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
2314 def parent = a.parent()
2316 fileAssociationActions.each { faa ->
2319 // don't need to continue in .any loop once replacements have been made
2324 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
2325 // NB we're deleting the /other/ one!
2326 // Also remove the examples subdir from non-release versions
2327 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
2328 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
2329 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
2330 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
2332 // remove the examples subdir from Full File Set
2333 def files = install4jConfigXml.files[0]
2334 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
2335 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
2336 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
2337 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
2338 dirEntry.parent().remove(dirEntry)
2340 install4jConfigXml.'**'.action.any { a ->
2341 if (a.'@customizedId' == customizedIdToDelete) {
2342 def parent = a.parent()
2348 // write install4j file
2349 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2356 delete install4jConfFile
2360 task cleanInstallersDataFiles {
2361 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2362 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2363 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2365 delete installersOutputTxt
2366 delete installersSha256
2367 delete hugoDataJsonFile
2371 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2372 group = "distribution"
2373 description = "Create the install4j installers"
2375 dependsOn copyInstall4jTemplate
2376 dependsOn cleanInstallersDataFiles
2378 projectFile = install4jConfFile
2380 // create an md5 for the input files to use as version for install4j conf file
2381 def digest = MessageDigest.getInstance("MD5")
2383 (file("${install4jDir}/${install4j_template}").text +
2384 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2385 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2386 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2387 if (filesMd5.length() >= 8) {
2388 filesMd5 = filesMd5.substring(0,8)
2390 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2393 'JALVIEW_NAME': jalview_name,
2394 'JALVIEW_APPLICATION_NAME': applicationName,
2395 'JALVIEW_DIR': "../..",
2396 'OSX_KEYSTORE': OSX_KEYSTORE,
2397 'OSX_APPLEID': OSX_APPLEID,
2398 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2399 'JSIGN_SH': JSIGN_SH,
2400 'JRE_DIR': getdown_app_dir_java,
2401 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2402 'JALVIEW_VERSION': JALVIEW_VERSION,
2403 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2404 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2405 'JAVA_VERSION': JAVA_VERSION,
2406 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2407 'VERSION': JALVIEW_VERSION,
2408 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2409 'BUNDLE_ID': install4jBundleId,
2410 'INTERNAL_ID': install4jInternalId,
2411 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2412 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2413 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2414 'WRAPPER_LINK': getdownWrapperLink,
2415 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2416 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2417 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2418 'INSTALLER_NAME': install4jInstallerName,
2419 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2420 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2421 'GETDOWN_FILES_DIR': getdown_files_dir,
2422 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2423 'GETDOWN_DIST_DIR': getdownAppDistDir,
2424 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2425 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2426 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2427 'BUILD_DIR': install4jBuildDir,
2428 'APPLICATION_CATEGORIES': install4j_application_categories,
2429 'APPLICATION_FOLDER': install4jApplicationFolder,
2430 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2431 'EXECUTABLE_NAME': install4jExecutableName,
2432 'EXTRA_SCHEME': install4jExtraScheme,
2433 'MAC_ICONS_FILE': install4jMacIconsFile,
2434 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2435 'PNG_ICON_FILE': install4jPngIconFile,
2436 'BACKGROUND': install4jBackground,
2441 'windows': 'WINDOWS',
2445 // these are the bundled OS/architecture VMs needed by install4j
2448 [ "mac", "aarch64" ],
2449 [ "windows", "x64" ],
2451 [ "linux", "aarch64" ]
2453 osArch.forEach { os, arch ->
2454 variables[ sprintf("%s_%s_JAVA_VM_DIR", varNameMap[os], arch.toUpperCase(Locale.ROOT)) ] = sprintf("%s/jre-%s-%s-%s/jre", jreInstallsDir, JAVA_INTEGER_VERSION, os, arch)
2455 // N.B. For some reason install4j requires the below filename to have underscores and not hyphens
2456 // otherwise running `gradle installers` generates a non-useful error:
2457 // `install4j: compilation failed. Reason: java.lang.NumberFormatException: For input string: "windows"`
2458 variables[ sprintf("%s_%s_JAVA_VM_TGZ", varNameMap[os], arch.toUpperCase(Locale.ROOT)) ] = sprintf("%s/tgz/jre_%s_%s_%s.tar.gz", jreInstallsDir, JAVA_INTEGER_VERSION, os, arch)
2461 //println("INSTALL4J VARIABLES:")
2462 //variables.each{k,v->println("${k}=${v}")}
2464 destination = "${jalviewDir}/${install4jBuildDir}"
2465 buildSelected = true
2467 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2469 disableSigning = true
2470 disableNotarization = true
2474 macKeystorePassword = OSX_KEYPASS
2477 if (OSX_ALTOOLPASS) {
2478 appleIdPassword = OSX_ALTOOLPASS
2479 disableNotarization = false
2481 disableNotarization = true
2485 println("Using projectFile "+projectFile)
2486 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2490 inputs.dir(getdownAppBaseDir)
2491 inputs.file(install4jConfFile)
2492 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2493 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2496 def getDataHash(File myFile) {
2497 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2498 return myFile.exists()
2500 "file" : myFile.getName(),
2501 "filesize" : myFile.length(),
2502 "sha256" : hash.toString()
2507 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2509 "channel" : getdownChannelName,
2510 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2511 "git-commit" : "${gitHash} [${gitBranch}]",
2512 "version" : JALVIEW_VERSION
2514 // install4j installer files
2515 if (installersOutputTxt.exists()) {
2517 installersOutputTxt.readLines().each { def line ->
2518 if (line.startsWith("#")) {
2521 line.replaceAll("\n","")
2522 def vals = line.split("\t")
2523 def filename = vals[3]
2524 def filesize = file(filename).length()
2525 filename = filename.replaceAll(/^.*\//, "")
2526 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2527 idHash."${filename}" = vals[0]
2529 if (install4jCheckSums && installersSha256.exists()) {
2530 installersSha256.readLines().each { def line ->
2531 if (line.startsWith("#")) {
2534 line.replaceAll("\n","")
2535 def vals = line.split(/\s+\*?/)
2536 def filename = vals[1]
2537 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2543 "JAR": shadowJar.archiveFile, // executable JAR
2544 "JVL": getdownVersionLaunchJvl, // version JVL
2545 "SOURCE": sourceDist.archiveFile // source TGZ
2546 ].each { key, value ->
2547 def file = file(value)
2548 if (file.exists()) {
2549 def fileHash = getDataHash(file)
2550 if (fileHash != null) {
2551 hash."${key}" = fileHash;
2555 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2558 task staticMakeInstallersJsonFile {
2560 def output = findProperty("i4j_output")
2561 def sha256 = findProperty("i4j_sha256")
2562 def json = findProperty("i4j_json")
2563 if (output == null || sha256 == null || json == null) {
2564 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2566 writeDataJsonFile(file(output), file(sha256), file(json))
2571 dependsOn installerFiles
2577 eclipse().configFile(eclipse_codestyle_file)
2581 task createSourceReleaseProperties(type: WriteProperties) {
2582 group = "distribution"
2583 description = "Create the source RELEASE properties file"
2585 def sourceTarBuildDir = "${buildDir}/sourceTar"
2586 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2587 outputFile (sourceReleasePropertiesFile)
2590 releaseProps.each{ key, val -> property key, val }
2591 property "git.branch", gitBranch
2592 property "git.hash", gitHash
2595 outputs.file(outputFile)
2598 task sourceDist(type: Tar) {
2599 group "distribution"
2600 description "Create a source .tar.gz file for distribution"
2602 dependsOn createBuildProperties
2603 dependsOn convertMdFiles
2604 dependsOn eclipseAllPreferences
2605 dependsOn createSourceReleaseProperties
2608 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2609 archiveFileName = outputFileName
2611 compression Compression.GZIP
2626 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2628 "utils/InstallAnywhere",
2643 "gradle.properties",
2655 ".settings/org.eclipse.buildship.core.prefs",
2656 ".settings/org.eclipse.jdt.core.prefs"
2660 exclude (EXCLUDE_FILES)
2661 include (PROCESS_FILES)
2662 filter(ReplaceTokens,
2666 'Version-Rel': JALVIEW_VERSION,
2667 'Year-Rel': getDate("yyyy")
2672 exclude (EXCLUDE_FILES)
2673 exclude (PROCESS_FILES)
2674 exclude ("appletlib")
2675 exclude ("**/*locales")
2676 exclude ("*locales/**")
2677 exclude ("utils/InstallAnywhere")
2679 exclude (getdown_files_dir)
2680 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2681 //exclude (getdown_website_dir)
2682 //exclude (getdown_archive_dir)
2684 // exluding these as not using jars as modules yet
2685 exclude ("${j11modDir}/**/*.jar")
2688 include(INCLUDE_FILES)
2690 // from (jalviewDir) {
2691 // // explicit includes for stuff that seemed to not get included
2692 // include(fileTree("test/**/*."))
2693 // exclude(EXCLUDE_FILES)
2694 // exclude(PROCESS_FILES)
2697 from(file(buildProperties).getParent()) {
2698 include(file(buildProperties).getName())
2699 rename(file(buildProperties).getName(), "build_properties")
2701 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2705 def sourceTarBuildDir = "${buildDir}/sourceTar"
2706 from(sourceTarBuildDir) {
2707 // this includes the appended RELEASE properties file
2711 task dataInstallersJson {
2713 description "Create the installers-VERSION.json data file for installer files created"
2715 mustRunAfter installers
2716 mustRunAfter shadowJar
2717 mustRunAfter sourceDist
2718 mustRunAfter getdownArchive
2720 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2721 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2723 if (installersOutputTxt.exists()) {
2724 inputs.file(installersOutputTxt)
2726 if (install4jCheckSums && installersSha256.exists()) {
2727 inputs.file(installersSha256)
2730 shadowJar.archiveFile, // executable JAR
2731 getdownVersionLaunchJvl, // version JVL
2732 sourceDist.archiveFile // source TGZ
2733 ].each { fileName ->
2734 if (file(fileName).exists()) {
2735 inputs.file(fileName)
2739 outputs.file(hugoDataJsonFile)
2742 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2748 description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'."
2751 dependsOn pubhtmlhelp
2753 inputs.dir("${helpBuildDir}/${help_dir}")
2754 outputs.dir("${buildDir}/distributions/${help_dir}")
2758 task j2sSetHeadlessBuild {
2765 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2767 description "Enable the alternative J2S Config file for headless build"
2769 outputFile = jalviewjsJ2sSettingsFileName
2770 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2771 def j2sProps = new Properties()
2772 if (j2sPropsFile.exists()) {
2774 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2775 j2sProps.load(j2sPropsFileFIS)
2776 j2sPropsFileFIS.close()
2778 j2sProps.each { prop, val ->
2781 } catch (Exception e) {
2782 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2786 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2787 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2792 task jalviewjsSetEclipseWorkspace {
2793 def propKey = "jalviewjs_eclipse_workspace"
2795 if (project.hasProperty(propKey)) {
2796 propVal = project.getProperty(propKey)
2797 if (propVal.startsWith("~/")) {
2798 propVal = System.getProperty("user.home") + propVal.substring(1)
2801 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2802 def propsFile = file(propsFileName)
2803 def eclipseWsDir = propVal
2804 def props = new Properties()
2806 def writeProps = true
2807 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2808 def ins = new FileInputStream(propsFileName)
2811 if (props.getProperty(propKey, null) != null) {
2812 eclipseWsDir = props.getProperty(propKey)
2817 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2818 def tempDir = File.createTempDir()
2819 eclipseWsDir = tempDir.getAbsolutePath()
2822 eclipseWorkspace = file(eclipseWsDir)
2825 // do not run a headless transpile when we claim to be in Eclipse
2827 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2828 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2830 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2834 props.setProperty(propKey, eclipseWsDir)
2835 propsFile.parentFile.mkdirs()
2836 def bytes = new ByteArrayOutputStream()
2837 props.store(bytes, null)
2838 def propertiesString = bytes.toString()
2839 propsFile.text = propertiesString
2845 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2848 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2849 outputs.file(propsFileName)
2850 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2854 task jalviewjsEclipsePaths {
2857 def eclipseRoot = jalviewjs_eclipse_root
2858 if (eclipseRoot.startsWith("~/")) {
2859 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2861 if (OperatingSystem.current().isMacOsX()) {
2862 eclipseRoot += "/Eclipse.app"
2863 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2864 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2865 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2866 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2867 eclipseRoot += "/eclipse"
2869 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2870 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2871 } else { // linux or unix
2872 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2873 eclipseRoot += "/eclipse"
2874 println("eclipseDir exists")
2876 eclipseBinary = "${eclipseRoot}/eclipse"
2877 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2880 eclipseVersion = "4.13" // default
2881 def assumedVersion = true
2882 if (file(eclipseProduct).exists()) {
2883 def fis = new FileInputStream(eclipseProduct)
2884 def props = new Properties()
2886 eclipseVersion = props.getProperty("version")
2888 assumedVersion = false
2891 def propKey = "eclipse_debug"
2892 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2895 // do not run a headless transpile when we claim to be in Eclipse
2897 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2898 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2900 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2903 if (!assumedVersion) {
2904 println("ECLIPSE VERSION=${eclipseVersion}")
2910 task printProperties {
2912 description "Output to console all System.properties"
2914 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2920 dependsOn eclipseProject
2921 dependsOn eclipseClasspath
2922 dependsOn eclipseJdt
2926 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2927 task jalviewjsEclipseCopyDropins(type: Copy) {
2928 dependsOn jalviewjsEclipsePaths
2930 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2931 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2932 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2939 // this eclipse -clean doesn't actually work
2940 task jalviewjsCleanEclipse(type: Exec) {
2941 dependsOn eclipseSetup
2942 dependsOn jalviewjsEclipsePaths
2943 dependsOn jalviewjsEclipseCopyDropins
2945 executable(eclipseBinary)
2946 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2952 def inputString = """exit
2955 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2956 standardInput = inputByteStream
2959 /* not really working yet
2960 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2964 task jalviewjsTransferUnzipSwingJs {
2965 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2969 from zipTree(file_zip)
2970 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2974 inputs.file file_zip
2975 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2979 task jalviewjsTransferUnzipLib {
2980 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2983 zipFiles.each { file_zip ->
2985 from zipTree(file_zip)
2986 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2991 inputs.files zipFiles
2992 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2996 task jalviewjsTransferUnzipAllLibs {
2997 dependsOn jalviewjsTransferUnzipSwingJs
2998 dependsOn jalviewjsTransferUnzipLib
3002 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
3004 description "Create the alternative j2s file from the j2s.* properties"
3006 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
3007 def siteDirProperty = "j2s.site.directory"
3008 def setSiteDir = false
3009 jalviewjsJ2sProps.each { prop, val ->
3011 if (prop == siteDirProperty) {
3012 if (!(val.startsWith('/') || val.startsWith("file://") )) {
3013 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3019 if (!setSiteDir) { // default site location, don't override specifically set property
3020 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3023 outputFile = jalviewjsJ2sAltSettingsFileName
3026 inputs.properties(jalviewjsJ2sProps)
3027 outputs.file(jalviewjsJ2sAltSettingsFileName)
3032 task jalviewjsEclipseSetup {
3033 dependsOn jalviewjsEclipseCopyDropins
3034 dependsOn jalviewjsSetEclipseWorkspace
3035 dependsOn jalviewjsCreateJ2sSettings
3039 task jalviewjsSyncAllLibs (type: Sync) {
3040 dependsOn jalviewjsTransferUnzipAllLibs
3041 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3042 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3043 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3047 def outputFiles = []
3048 rename { filename ->
3049 outputFiles += "${outputDir}/${filename}"
3056 // should this be exclude really ?
3057 duplicatesStrategy "INCLUDE"
3059 outputs.files outputFiles
3060 inputs.files inputFiles
3064 task jalviewjsSyncResources (type: Sync) {
3065 dependsOn buildResources
3067 def inputFiles = fileTree(dir: resourcesBuildDir)
3068 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3072 def outputFiles = []
3073 rename { filename ->
3074 outputFiles += "${outputDir}/${filename}"
3080 outputs.files outputFiles
3081 inputs.files inputFiles
3085 task jalviewjsSyncSiteResources (type: Sync) {
3086 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3087 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3091 def outputFiles = []
3092 rename { filename ->
3093 outputFiles += "${outputDir}/${filename}"
3099 outputs.files outputFiles
3100 inputs.files inputFiles
3104 task jalviewjsSyncBuildProperties (type: Sync) {
3105 dependsOn createBuildProperties
3106 def inputFiles = [file(buildProperties)]
3107 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3111 def outputFiles = []
3112 rename { filename ->
3113 outputFiles += "${outputDir}/${filename}"
3119 outputs.files outputFiles
3120 inputs.files inputFiles
3124 task jalviewjsProjectImport(type: Exec) {
3125 dependsOn eclipseSetup
3126 dependsOn jalviewjsEclipsePaths
3127 dependsOn jalviewjsEclipseSetup
3130 // do not run a headless import when we claim to be in Eclipse
3132 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3133 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3135 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3139 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3140 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3141 executable(eclipseBinary)
3142 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3146 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3148 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3149 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3152 inputs.file("${jalviewDir}/.project")
3153 outputs.upToDateWhen {
3154 file(projdir).exists()
3159 task jalviewjsTranspile(type: Exec) {
3160 dependsOn jalviewjsEclipseSetup
3161 dependsOn jalviewjsProjectImport
3162 dependsOn jalviewjsEclipsePaths
3164 dependsOn jalviewjsEnableAltFileProperty
3168 // do not run a headless transpile when we claim to be in Eclipse
3170 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3171 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3173 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3177 executable(eclipseBinary)
3178 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3182 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3184 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3185 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3191 stdout = new ByteArrayOutputStream()
3192 stderr = new ByteArrayOutputStream()
3194 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3195 def logOutFile = file(logOutFileName)
3196 logOutFile.createNewFile()
3197 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3198 BINARY: ${eclipseBinary}
3199 VERSION: ${eclipseVersion}
3200 WORKSPACE: ${eclipseWorkspace}
3201 DEBUG: ${eclipseDebug}
3204 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3205 // combine stdout and stderr
3206 def logErrFOS = logOutFOS
3208 if (jalviewjs_j2s_to_console.equals("true")) {
3209 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3210 new org.apache.tools.ant.util.TeeOutputStream(
3214 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3215 new org.apache.tools.ant.util.TeeOutputStream(
3220 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3223 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3230 if (stdout.toString().contains("Error processing ")) {
3231 // j2s did not complete transpile
3232 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3233 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3234 println("IGNORING TRANSPILE ERRORS")
3235 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3237 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3242 inputs.dir("${jalviewDir}/${sourceDir}")
3243 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3244 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3248 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3250 def stdout = new ByteArrayOutputStream()
3251 def stderr = new ByteArrayOutputStream()
3253 def coreFile = file(jsfile)
3255 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3257 logOutFile.createNewFile()
3258 logOutFile.append(msg+"\n")
3260 def coreTop = file(prefixFile)
3261 def coreBottom = file(suffixFile)
3262 coreFile.getParentFile().mkdirs()
3263 coreFile.createNewFile()
3264 coreFile.write( coreTop.getText("UTF-8") )
3268 def t = f.getText("UTF-8")
3269 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3270 coreFile.append( t )
3272 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3274 logOutFile.append(msg+"\n")
3277 coreFile.append( coreBottom.getText("UTF-8") )
3279 msg = "Generating ${zjsfile}"
3281 logOutFile.append(msg+"\n")
3282 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3283 def logErrFOS = logOutFOS
3286 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3287 main = "com.google.javascript.jscomp.CommandLineRunner"
3288 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3289 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3292 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3294 logOutFile.append(msg+"\n")
3296 if (logOutConsole) {
3297 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3298 new org.apache.tools.ant.util.TeeOutputStream(
3302 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3303 new org.apache.tools.ant.util.TeeOutputStream(
3308 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3311 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3318 logOutFile.append(msg+"\n")
3322 task jalviewjsBuildAllCores {
3324 description "Build the core js lib closures listed in the classlists dir"
3325 dependsOn jalviewjsTranspile
3326 dependsOn jalviewjsTransferUnzipSwingJs
3328 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3329 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3330 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3331 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3332 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3333 def prefixFile = "${jsDir}/core/coretop2.js"
3334 def suffixFile = "${jsDir}/core/corebottom2.js"
3336 inputs.file prefixFile
3337 inputs.file suffixFile
3339 def classlistFiles = []
3340 // add the classlists found int the jalviewjs_classlists_dir
3341 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3343 def name = file.getName() - ".txt"
3350 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3351 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3352 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3354 jalviewjsCoreClasslists = []
3356 classlistFiles.each {
3359 def file = hash['file']
3360 if (! file.exists()) {
3361 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3362 return false // this is a "continue" in groovy .each closure
3364 def name = hash['name']
3366 name = file.getName() - ".txt"
3374 def list = fileTree(dir: j2sDir, includes: filelist)
3376 def jsfile = "${outputDir}/core${name}.js"
3377 def zjsfile = "${outputDir}/core${name}.z.js"
3379 jalviewjsCoreClasslists += [
3388 outputs.file(jsfile)
3389 outputs.file(zjsfile)
3392 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3393 def stevesoftClasslistName = "_stevesoft"
3394 def stevesoftClasslist = [
3395 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3396 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3397 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3398 'name': stevesoftClasslistName
3400 jalviewjsCoreClasslists += stevesoftClasslist
3401 inputs.files(stevesoftClasslist['list'])
3402 outputs.file(stevesoftClasslist['jsfile'])
3403 outputs.file(stevesoftClasslist['zjsfile'])
3406 def allClasslistName = "_all"
3407 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3408 allJsFiles += fileTree(
3412 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3413 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3414 "**/org/jmol/export/JSExporter.js"
3417 allJsFiles += fileTree(
3421 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3422 "**/sun/misc/Unsafe.js",
3423 "**/swingjs/jquery/jquery-editable-select.js",
3424 "**/swingjs/jquery/j2sComboBox.js",
3425 "**/sun/misc/FloatingDecimal.js"
3428 def allClasslist = [
3429 'jsfile': "${outputDir}/core${allClasslistName}.js",
3430 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3432 'name': allClasslistName
3434 // not including this version of "all" core at the moment
3435 //jalviewjsCoreClasslists += allClasslist
3436 inputs.files(allClasslist['list'])
3437 outputs.file(allClasslist['jsfile'])
3438 outputs.file(allClasslist['zjsfile'])
3441 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3442 logOutFile.getParentFile().mkdirs()
3443 logOutFile.createNewFile()
3444 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3446 jalviewjsCoreClasslists.each {
3447 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3454 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3457 into file(outputFile).getParentFile()
3458 rename { filename ->
3459 if (filename.equals(inputFile.getName())) {
3460 return file(outputFile).getName()
3464 filter(ReplaceTokens,
3468 'MAIN': '"'+main_class+'"',
3470 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3471 'COREKEY': jalviewjs_core_key,
3472 'CORENAME': coreName
3479 task jalviewjsPublishCoreTemplates {
3480 dependsOn jalviewjsBuildAllCores
3481 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3482 def inputFile = file(inputFileName)
3483 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3485 def outputFiles = []
3486 jalviewjsCoreClasslists.each { cl ->
3487 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3488 cl['outputfile'] = outputFile
3489 outputFiles += outputFile
3493 jalviewjsCoreClasslists.each { cl ->
3494 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3497 inputs.file(inputFile)
3498 outputs.files(outputFiles)
3502 task jalviewjsSyncCore (type: Sync) {
3503 dependsOn jalviewjsBuildAllCores
3504 dependsOn jalviewjsPublishCoreTemplates
3505 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3506 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3510 def outputFiles = []
3511 rename { filename ->
3512 outputFiles += "${outputDir}/${filename}"
3518 outputs.files outputFiles
3519 inputs.files inputFiles
3523 // this Copy version of TransferSiteJs will delete anything else in the target dir
3524 task jalviewjsCopyTransferSiteJs(type: Copy) {
3525 dependsOn jalviewjsTranspile
3526 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3527 into "${jalviewDir}/${jalviewjsSiteDir}"
3531 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3532 task jalviewjsSyncTransferSiteJs(type: Sync) {
3533 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3535 into "${jalviewDir}/${jalviewjsSiteDir}"
3542 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3543 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3544 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3545 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3547 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3548 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3549 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3550 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3553 task jalviewjsPrepareSite {
3555 description "Prepares the website folder including unzipping files and copying resources"
3556 dependsOn jalviewjsSyncAllLibs
3557 dependsOn jalviewjsSyncResources
3558 dependsOn jalviewjsSyncSiteResources
3559 dependsOn jalviewjsSyncBuildProperties
3560 dependsOn jalviewjsSyncCore
3564 task jalviewjsBuildSite {
3566 description "Builds the whole website including transpiled code"
3567 dependsOn jalviewjsCopyTransferSiteJs
3568 dependsOn jalviewjsPrepareSite
3572 task cleanJalviewjsTransferSite {
3574 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3575 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3576 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3577 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3582 task cleanJalviewjsSite {
3583 dependsOn cleanJalviewjsTransferSite
3585 delete "${jalviewDir}/${jalviewjsSiteDir}"
3590 task jalviewjsSiteTar(type: Tar) {
3592 description "Creates a tar.gz file for the website"
3593 dependsOn jalviewjsBuildSite
3594 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3595 archiveFileName = outputFilename
3597 compression Compression.GZIP
3599 from "${jalviewDir}/${jalviewjsSiteDir}"
3600 into jalviewjs_site_dir // this is inside the tar file
3602 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3606 task jalviewjsServer {
3608 def filename = "jalviewjsTest.html"
3609 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3610 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3615 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3616 factory = f.newInstance()
3617 } catch (ClassNotFoundException e) {
3618 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3620 def port = Integer.valueOf(jalviewjs_server_port)
3625 while(port < start+1000 && !running) {
3627 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3628 jalviewjsServer = factory.start(doc_root, port)
3630 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3631 println("SERVER STARTED with document root ${doc_root}.")
3632 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3633 println("For debug: "+url+"?j2sdebug")
3634 println("For verbose: "+url+"?j2sverbose")
3635 } catch (Exception e) {
3640 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3641 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3642 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3644 jalviewjsCoreClasslists.each { cl ->
3645 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3647 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3649 println("For core ${cl.name}: "+urlcore)
3652 file(htmlFile).text = htmlText
3655 outputs.file(htmlFile)
3656 outputs.upToDateWhen({false})
3660 task cleanJalviewjsAll {
3662 description "Delete all configuration and build artifacts to do with JalviewJS build"
3663 dependsOn cleanJalviewjsSite
3664 dependsOn jalviewjsEclipsePaths
3667 delete "${jalviewDir}/${jalviewjsBuildDir}"
3668 delete "${jalviewDir}/${eclipse_bin_dir}"
3669 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3670 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3672 delete jalviewjsJ2sAltSettingsFileName
3675 outputs.upToDateWhen( { false } )
3679 task jalviewjsIDE_checkJ2sPlugin {
3680 group "00 JalviewJS in Eclipse"
3681 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3684 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3685 def j2sPluginFile = file(j2sPlugin)
3686 def eclipseHome = System.properties["eclipse.home.location"]
3687 if (eclipseHome == null || ! IN_ECLIPSE) {
3688 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3690 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3691 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3692 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3693 eclipseJ2sPluginDirs += altPluginsDir
3695 def foundPlugin = false
3696 def j2sPluginFileName = j2sPluginFile.getName()
3697 def eclipseJ2sPlugin
3698 def eclipseJ2sPluginFile
3699 eclipseJ2sPluginDirs.any { dir ->
3700 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3701 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3702 if (eclipseJ2sPluginFile.exists()) {
3708 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3709 System.err.println(msg)
3710 throw new StopExecutionException(msg)
3713 def digest = MessageDigest.getInstance("MD5")
3715 digest.update(j2sPluginFile.text.bytes)
3716 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3718 digest.update(eclipseJ2sPluginFile.text.bytes)
3719 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3721 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3722 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3723 System.err.println(msg)
3724 throw new StopExecutionException(msg)
3726 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3732 task jalviewjsIDE_copyJ2sPlugin {
3733 group "00 JalviewJS in Eclipse"
3734 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3737 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3738 def j2sPluginFile = file(j2sPlugin)
3739 def eclipseHome = System.properties["eclipse.home.location"]
3740 if (eclipseHome == null || ! IN_ECLIPSE) {
3741 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3743 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3744 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3745 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3746 System.err.println(msg)
3749 eclipseJ2sPluginFile.getParentFile().mkdirs()
3750 into eclipseJ2sPluginFile.getParent()
3756 task jalviewjsIDE_j2sFile {
3757 group "00 JalviewJS in Eclipse"
3758 description "Creates the .j2s file"
3759 dependsOn jalviewjsCreateJ2sSettings
3763 task jalviewjsIDE_SyncCore {
3764 group "00 JalviewJS in Eclipse"
3765 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3766 dependsOn jalviewjsSyncCore
3770 task jalviewjsIDE_SyncSiteAll {
3771 dependsOn jalviewjsSyncAllLibs
3772 dependsOn jalviewjsSyncResources
3773 dependsOn jalviewjsSyncSiteResources
3774 dependsOn jalviewjsSyncBuildProperties
3778 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3781 task jalviewjsIDE_PrepareSite {
3782 group "00 JalviewJS in Eclipse"
3783 description "Sync libs and resources to site dir, but not closure cores"
3785 dependsOn jalviewjsIDE_SyncSiteAll
3786 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3790 task jalviewjsIDE_AssembleSite {
3791 group "00 JalviewJS in Eclipse"
3792 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3793 dependsOn jalviewjsPrepareSite
3797 task jalviewjsIDE_SiteClean {
3798 group "00 JalviewJS in Eclipse"
3799 description "Deletes the Eclipse transpiled site"
3800 dependsOn cleanJalviewjsSite
3804 task jalviewjsIDE_Server {
3805 group "00 JalviewJS in Eclipse"
3806 description "Starts a webserver on localhost to test the website"
3807 dependsOn jalviewjsServer
3811 // buildship runs this at import or gradle refresh
3812 task eclipseSynchronizationTask {
3813 //dependsOn eclipseSetup
3814 dependsOn createBuildProperties
3816 dependsOn jalviewjsIDE_j2sFile
3817 dependsOn jalviewjsIDE_checkJ2sPlugin
3818 dependsOn jalviewjsIDE_PrepareSite
3823 // buildship runs this at build time or project refresh
3824 task eclipseAutoBuildTask {
3825 //dependsOn jalviewjsIDE_checkJ2sPlugin
3826 //dependsOn jalviewjsIDE_PrepareSite
3832 description "Build the site"
3833 dependsOn jalviewjsBuildSite