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 '9.0.6'
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,
2409 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2410 'BUNDLE_ID': install4jBundleId,
2411 'INTERNAL_ID': install4jInternalId,
2412 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2413 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2414 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2415 'WRAPPER_LINK': getdownWrapperLink,
2416 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2417 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2418 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2419 'INSTALLER_NAME': install4jInstallerName,
2420 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2421 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2422 'GETDOWN_FILES_DIR': getdown_files_dir,
2423 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2424 'GETDOWN_DIST_DIR': getdownAppDistDir,
2425 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2426 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2427 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2428 'BUILD_DIR': install4jBuildDir,
2429 'APPLICATION_CATEGORIES': install4j_application_categories,
2430 'APPLICATION_FOLDER': install4jApplicationFolder,
2431 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2432 'EXECUTABLE_NAME': install4jExecutableName,
2433 'EXTRA_SCHEME': install4jExtraScheme,
2434 'MAC_ICONS_FILE': install4jMacIconsFile,
2435 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2436 'PNG_ICON_FILE': install4jPngIconFile,
2437 'BACKGROUND': install4jBackground,
2441 //macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
2442 //windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
2443 //linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
2444 //macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
2445 //windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
2446 //linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
2450 'windows': 'WINDOWS',
2454 // these are the bundled OS/architecture VMs needed by install4j
2457 [ "mac", "aarch64" ],
2458 [ "windows", "x64" ],
2460 [ "linux", "aarch64" ]
2462 osArch.forEach { os, arch ->
2463 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)
2464 // N.B. For some reason install4j requires the below filename to have underscores and not hyphens
2465 // otherwise running `gradle installers` generates a non-useful error:
2466 // `install4j: compilation failed. Reason: java.lang.NumberFormatException: For input string: "windows"`
2467 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)
2470 println("INSTALL4J VARIABLES:")
2471 variables.each{k,v->println("${k}=${v}")}
2473 destination = "${jalviewDir}/${install4jBuildDir}"
2474 buildSelected = true
2476 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2478 disableSigning = true
2479 disableNotarization = true
2483 macKeystorePassword = OSX_KEYPASS
2486 if (OSX_ALTOOLPASS) {
2487 appleIdPassword = OSX_ALTOOLPASS
2488 disableNotarization = false
2490 disableNotarization = true
2494 println("Using projectFile "+projectFile)
2495 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2499 inputs.dir(getdownAppBaseDir)
2500 inputs.file(install4jConfFile)
2501 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2502 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2505 def getDataHash(File myFile) {
2506 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2507 return myFile.exists()
2509 "file" : myFile.getName(),
2510 "filesize" : myFile.length(),
2511 "sha256" : hash.toString()
2516 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2518 "channel" : getdownChannelName,
2519 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2520 "git-commit" : "${gitHash} [${gitBranch}]",
2521 "version" : JALVIEW_VERSION
2523 // install4j installer files
2524 if (installersOutputTxt.exists()) {
2526 installersOutputTxt.readLines().each { def line ->
2527 if (line.startsWith("#")) {
2530 line.replaceAll("\n","")
2531 def vals = line.split("\t")
2532 def filename = vals[3]
2533 def filesize = file(filename).length()
2534 filename = filename.replaceAll(/^.*\//, "")
2535 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2536 idHash."${filename}" = vals[0]
2538 if (install4jCheckSums && installersSha256.exists()) {
2539 installersSha256.readLines().each { def line ->
2540 if (line.startsWith("#")) {
2543 line.replaceAll("\n","")
2544 def vals = line.split(/\s+\*?/)
2545 def filename = vals[1]
2546 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2552 "JAR": shadowJar.archiveFile, // executable JAR
2553 "JVL": getdownVersionLaunchJvl, // version JVL
2554 "SOURCE": sourceDist.archiveFile // source TGZ
2555 ].each { key, value ->
2556 def file = file(value)
2557 if (file.exists()) {
2558 def fileHash = getDataHash(file)
2559 if (fileHash != null) {
2560 hash."${key}" = fileHash;
2564 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2567 task staticMakeInstallersJsonFile {
2569 def output = findProperty("i4j_output")
2570 def sha256 = findProperty("i4j_sha256")
2571 def json = findProperty("i4j_json")
2572 if (output == null || sha256 == null || json == null) {
2573 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2575 writeDataJsonFile(file(output), file(sha256), file(json))
2580 dependsOn installerFiles
2586 eclipse().configFile(eclipse_codestyle_file)
2590 task createSourceReleaseProperties(type: WriteProperties) {
2591 group = "distribution"
2592 description = "Create the source RELEASE properties file"
2594 def sourceTarBuildDir = "${buildDir}/sourceTar"
2595 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2596 outputFile (sourceReleasePropertiesFile)
2599 releaseProps.each{ key, val -> property key, val }
2600 property "git.branch", gitBranch
2601 property "git.hash", gitHash
2604 outputs.file(outputFile)
2607 task sourceDist(type: Tar) {
2608 group "distribution"
2609 description "Create a source .tar.gz file for distribution"
2611 dependsOn createBuildProperties
2612 dependsOn convertMdFiles
2613 dependsOn eclipseAllPreferences
2614 dependsOn createSourceReleaseProperties
2617 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2618 archiveFileName = outputFileName
2620 compression Compression.GZIP
2635 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2637 "utils/InstallAnywhere",
2652 "gradle.properties",
2664 ".settings/org.eclipse.buildship.core.prefs",
2665 ".settings/org.eclipse.jdt.core.prefs"
2669 exclude (EXCLUDE_FILES)
2670 include (PROCESS_FILES)
2671 filter(ReplaceTokens,
2675 'Version-Rel': JALVIEW_VERSION,
2676 'Year-Rel': getDate("yyyy")
2681 exclude (EXCLUDE_FILES)
2682 exclude (PROCESS_FILES)
2683 exclude ("appletlib")
2684 exclude ("**/*locales")
2685 exclude ("*locales/**")
2686 exclude ("utils/InstallAnywhere")
2688 exclude (getdown_files_dir)
2689 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2690 //exclude (getdown_website_dir)
2691 //exclude (getdown_archive_dir)
2693 // exluding these as not using jars as modules yet
2694 exclude ("${j11modDir}/**/*.jar")
2697 include(INCLUDE_FILES)
2699 // from (jalviewDir) {
2700 // // explicit includes for stuff that seemed to not get included
2701 // include(fileTree("test/**/*."))
2702 // exclude(EXCLUDE_FILES)
2703 // exclude(PROCESS_FILES)
2706 from(file(buildProperties).getParent()) {
2707 include(file(buildProperties).getName())
2708 rename(file(buildProperties).getName(), "build_properties")
2710 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2714 def sourceTarBuildDir = "${buildDir}/sourceTar"
2715 from(sourceTarBuildDir) {
2716 // this includes the appended RELEASE properties file
2720 task dataInstallersJson {
2722 description "Create the installers-VERSION.json data file for installer files created"
2724 mustRunAfter installers
2725 mustRunAfter shadowJar
2726 mustRunAfter sourceDist
2727 mustRunAfter getdownArchive
2729 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2730 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2732 if (installersOutputTxt.exists()) {
2733 inputs.file(installersOutputTxt)
2735 if (install4jCheckSums && installersSha256.exists()) {
2736 inputs.file(installersSha256)
2739 shadowJar.archiveFile, // executable JAR
2740 getdownVersionLaunchJvl, // version JVL
2741 sourceDist.archiveFile // source TGZ
2742 ].each { fileName ->
2743 if (file(fileName).exists()) {
2744 inputs.file(fileName)
2748 outputs.file(hugoDataJsonFile)
2751 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2757 description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'."
2760 dependsOn pubhtmlhelp
2762 inputs.dir("${helpBuildDir}/${help_dir}")
2763 outputs.dir("${buildDir}/distributions/${help_dir}")
2767 task j2sSetHeadlessBuild {
2774 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2776 description "Enable the alternative J2S Config file for headless build"
2778 outputFile = jalviewjsJ2sSettingsFileName
2779 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2780 def j2sProps = new Properties()
2781 if (j2sPropsFile.exists()) {
2783 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2784 j2sProps.load(j2sPropsFileFIS)
2785 j2sPropsFileFIS.close()
2787 j2sProps.each { prop, val ->
2790 } catch (Exception e) {
2791 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2795 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2796 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2801 task jalviewjsSetEclipseWorkspace {
2802 def propKey = "jalviewjs_eclipse_workspace"
2804 if (project.hasProperty(propKey)) {
2805 propVal = project.getProperty(propKey)
2806 if (propVal.startsWith("~/")) {
2807 propVal = System.getProperty("user.home") + propVal.substring(1)
2810 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2811 def propsFile = file(propsFileName)
2812 def eclipseWsDir = propVal
2813 def props = new Properties()
2815 def writeProps = true
2816 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2817 def ins = new FileInputStream(propsFileName)
2820 if (props.getProperty(propKey, null) != null) {
2821 eclipseWsDir = props.getProperty(propKey)
2826 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2827 def tempDir = File.createTempDir()
2828 eclipseWsDir = tempDir.getAbsolutePath()
2831 eclipseWorkspace = file(eclipseWsDir)
2834 // do not run a headless transpile when we claim to be in Eclipse
2836 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2837 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2839 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2843 props.setProperty(propKey, eclipseWsDir)
2844 propsFile.parentFile.mkdirs()
2845 def bytes = new ByteArrayOutputStream()
2846 props.store(bytes, null)
2847 def propertiesString = bytes.toString()
2848 propsFile.text = propertiesString
2854 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2857 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2858 outputs.file(propsFileName)
2859 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2863 task jalviewjsEclipsePaths {
2866 def eclipseRoot = jalviewjs_eclipse_root
2867 if (eclipseRoot.startsWith("~/")) {
2868 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2870 if (OperatingSystem.current().isMacOsX()) {
2871 eclipseRoot += "/Eclipse.app"
2872 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2873 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2874 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2875 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2876 eclipseRoot += "/eclipse"
2878 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2879 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2880 } else { // linux or unix
2881 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2882 eclipseRoot += "/eclipse"
2883 println("eclipseDir exists")
2885 eclipseBinary = "${eclipseRoot}/eclipse"
2886 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2889 eclipseVersion = "4.13" // default
2890 def assumedVersion = true
2891 if (file(eclipseProduct).exists()) {
2892 def fis = new FileInputStream(eclipseProduct)
2893 def props = new Properties()
2895 eclipseVersion = props.getProperty("version")
2897 assumedVersion = false
2900 def propKey = "eclipse_debug"
2901 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2904 // do not run a headless transpile when we claim to be in Eclipse
2906 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2907 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2909 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2912 if (!assumedVersion) {
2913 println("ECLIPSE VERSION=${eclipseVersion}")
2919 task printProperties {
2921 description "Output to console all System.properties"
2923 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2929 dependsOn eclipseProject
2930 dependsOn eclipseClasspath
2931 dependsOn eclipseJdt
2935 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2936 task jalviewjsEclipseCopyDropins(type: Copy) {
2937 dependsOn jalviewjsEclipsePaths
2939 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2940 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2941 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2948 // this eclipse -clean doesn't actually work
2949 task jalviewjsCleanEclipse(type: Exec) {
2950 dependsOn eclipseSetup
2951 dependsOn jalviewjsEclipsePaths
2952 dependsOn jalviewjsEclipseCopyDropins
2954 executable(eclipseBinary)
2955 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2961 def inputString = """exit
2964 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2965 standardInput = inputByteStream
2968 /* not really working yet
2969 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2973 task jalviewjsTransferUnzipSwingJs {
2974 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2978 from zipTree(file_zip)
2979 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2983 inputs.file file_zip
2984 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2988 task jalviewjsTransferUnzipLib {
2989 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2992 zipFiles.each { file_zip ->
2994 from zipTree(file_zip)
2995 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3000 inputs.files zipFiles
3001 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3005 task jalviewjsTransferUnzipAllLibs {
3006 dependsOn jalviewjsTransferUnzipSwingJs
3007 dependsOn jalviewjsTransferUnzipLib
3011 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
3013 description "Create the alternative j2s file from the j2s.* properties"
3015 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
3016 def siteDirProperty = "j2s.site.directory"
3017 def setSiteDir = false
3018 jalviewjsJ2sProps.each { prop, val ->
3020 if (prop == siteDirProperty) {
3021 if (!(val.startsWith('/') || val.startsWith("file://") )) {
3022 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3028 if (!setSiteDir) { // default site location, don't override specifically set property
3029 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3032 outputFile = jalviewjsJ2sAltSettingsFileName
3035 inputs.properties(jalviewjsJ2sProps)
3036 outputs.file(jalviewjsJ2sAltSettingsFileName)
3041 task jalviewjsEclipseSetup {
3042 dependsOn jalviewjsEclipseCopyDropins
3043 dependsOn jalviewjsSetEclipseWorkspace
3044 dependsOn jalviewjsCreateJ2sSettings
3048 task jalviewjsSyncAllLibs (type: Sync) {
3049 dependsOn jalviewjsTransferUnzipAllLibs
3050 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3051 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3052 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3056 def outputFiles = []
3057 rename { filename ->
3058 outputFiles += "${outputDir}/${filename}"
3065 // should this be exclude really ?
3066 duplicatesStrategy "INCLUDE"
3068 outputs.files outputFiles
3069 inputs.files inputFiles
3073 task jalviewjsSyncResources (type: Sync) {
3074 dependsOn buildResources
3076 def inputFiles = fileTree(dir: resourcesBuildDir)
3077 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3081 def outputFiles = []
3082 rename { filename ->
3083 outputFiles += "${outputDir}/${filename}"
3089 outputs.files outputFiles
3090 inputs.files inputFiles
3094 task jalviewjsSyncSiteResources (type: Sync) {
3095 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3096 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3100 def outputFiles = []
3101 rename { filename ->
3102 outputFiles += "${outputDir}/${filename}"
3108 outputs.files outputFiles
3109 inputs.files inputFiles
3113 task jalviewjsSyncBuildProperties (type: Sync) {
3114 dependsOn createBuildProperties
3115 def inputFiles = [file(buildProperties)]
3116 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3120 def outputFiles = []
3121 rename { filename ->
3122 outputFiles += "${outputDir}/${filename}"
3128 outputs.files outputFiles
3129 inputs.files inputFiles
3133 task jalviewjsProjectImport(type: Exec) {
3134 dependsOn eclipseSetup
3135 dependsOn jalviewjsEclipsePaths
3136 dependsOn jalviewjsEclipseSetup
3139 // do not run a headless import when we claim to be in Eclipse
3141 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3142 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3144 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3148 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3149 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3150 executable(eclipseBinary)
3151 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3155 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3157 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3158 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3161 inputs.file("${jalviewDir}/.project")
3162 outputs.upToDateWhen {
3163 file(projdir).exists()
3168 task jalviewjsTranspile(type: Exec) {
3169 dependsOn jalviewjsEclipseSetup
3170 dependsOn jalviewjsProjectImport
3171 dependsOn jalviewjsEclipsePaths
3173 dependsOn jalviewjsEnableAltFileProperty
3177 // do not run a headless transpile when we claim to be in Eclipse
3179 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3180 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3182 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3186 executable(eclipseBinary)
3187 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3191 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3193 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3194 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3200 stdout = new ByteArrayOutputStream()
3201 stderr = new ByteArrayOutputStream()
3203 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3204 def logOutFile = file(logOutFileName)
3205 logOutFile.createNewFile()
3206 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3207 BINARY: ${eclipseBinary}
3208 VERSION: ${eclipseVersion}
3209 WORKSPACE: ${eclipseWorkspace}
3210 DEBUG: ${eclipseDebug}
3213 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3214 // combine stdout and stderr
3215 def logErrFOS = logOutFOS
3217 if (jalviewjs_j2s_to_console.equals("true")) {
3218 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3219 new org.apache.tools.ant.util.TeeOutputStream(
3223 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3224 new org.apache.tools.ant.util.TeeOutputStream(
3229 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3232 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3239 if (stdout.toString().contains("Error processing ")) {
3240 // j2s did not complete transpile
3241 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3242 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3243 println("IGNORING TRANSPILE ERRORS")
3244 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3246 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3251 inputs.dir("${jalviewDir}/${sourceDir}")
3252 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3253 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3257 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3259 def stdout = new ByteArrayOutputStream()
3260 def stderr = new ByteArrayOutputStream()
3262 def coreFile = file(jsfile)
3264 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3266 logOutFile.createNewFile()
3267 logOutFile.append(msg+"\n")
3269 def coreTop = file(prefixFile)
3270 def coreBottom = file(suffixFile)
3271 coreFile.getParentFile().mkdirs()
3272 coreFile.createNewFile()
3273 coreFile.write( coreTop.getText("UTF-8") )
3277 def t = f.getText("UTF-8")
3278 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3279 coreFile.append( t )
3281 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3283 logOutFile.append(msg+"\n")
3286 coreFile.append( coreBottom.getText("UTF-8") )
3288 msg = "Generating ${zjsfile}"
3290 logOutFile.append(msg+"\n")
3291 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3292 def logErrFOS = logOutFOS
3295 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3296 main = "com.google.javascript.jscomp.CommandLineRunner"
3297 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3298 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3301 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3303 logOutFile.append(msg+"\n")
3305 if (logOutConsole) {
3306 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3307 new org.apache.tools.ant.util.TeeOutputStream(
3311 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3312 new org.apache.tools.ant.util.TeeOutputStream(
3317 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3320 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3327 logOutFile.append(msg+"\n")
3331 task jalviewjsBuildAllCores {
3333 description "Build the core js lib closures listed in the classlists dir"
3334 dependsOn jalviewjsTranspile
3335 dependsOn jalviewjsTransferUnzipSwingJs
3337 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3338 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3339 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3340 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3341 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3342 def prefixFile = "${jsDir}/core/coretop2.js"
3343 def suffixFile = "${jsDir}/core/corebottom2.js"
3345 inputs.file prefixFile
3346 inputs.file suffixFile
3348 def classlistFiles = []
3349 // add the classlists found int the jalviewjs_classlists_dir
3350 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3352 def name = file.getName() - ".txt"
3359 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3360 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3361 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3363 jalviewjsCoreClasslists = []
3365 classlistFiles.each {
3368 def file = hash['file']
3369 if (! file.exists()) {
3370 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3371 return false // this is a "continue" in groovy .each closure
3373 def name = hash['name']
3375 name = file.getName() - ".txt"
3383 def list = fileTree(dir: j2sDir, includes: filelist)
3385 def jsfile = "${outputDir}/core${name}.js"
3386 def zjsfile = "${outputDir}/core${name}.z.js"
3388 jalviewjsCoreClasslists += [
3397 outputs.file(jsfile)
3398 outputs.file(zjsfile)
3401 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3402 def stevesoftClasslistName = "_stevesoft"
3403 def stevesoftClasslist = [
3404 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3405 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3406 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3407 'name': stevesoftClasslistName
3409 jalviewjsCoreClasslists += stevesoftClasslist
3410 inputs.files(stevesoftClasslist['list'])
3411 outputs.file(stevesoftClasslist['jsfile'])
3412 outputs.file(stevesoftClasslist['zjsfile'])
3415 def allClasslistName = "_all"
3416 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3417 allJsFiles += fileTree(
3421 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3422 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3423 "**/org/jmol/export/JSExporter.js"
3426 allJsFiles += fileTree(
3430 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3431 "**/sun/misc/Unsafe.js",
3432 "**/swingjs/jquery/jquery-editable-select.js",
3433 "**/swingjs/jquery/j2sComboBox.js",
3434 "**/sun/misc/FloatingDecimal.js"
3437 def allClasslist = [
3438 'jsfile': "${outputDir}/core${allClasslistName}.js",
3439 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3441 'name': allClasslistName
3443 // not including this version of "all" core at the moment
3444 //jalviewjsCoreClasslists += allClasslist
3445 inputs.files(allClasslist['list'])
3446 outputs.file(allClasslist['jsfile'])
3447 outputs.file(allClasslist['zjsfile'])
3450 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3451 logOutFile.getParentFile().mkdirs()
3452 logOutFile.createNewFile()
3453 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3455 jalviewjsCoreClasslists.each {
3456 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3463 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3466 into file(outputFile).getParentFile()
3467 rename { filename ->
3468 if (filename.equals(inputFile.getName())) {
3469 return file(outputFile).getName()
3473 filter(ReplaceTokens,
3477 'MAIN': '"'+main_class+'"',
3479 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3480 'COREKEY': jalviewjs_core_key,
3481 'CORENAME': coreName
3488 task jalviewjsPublishCoreTemplates {
3489 dependsOn jalviewjsBuildAllCores
3490 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3491 def inputFile = file(inputFileName)
3492 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3494 def outputFiles = []
3495 jalviewjsCoreClasslists.each { cl ->
3496 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3497 cl['outputfile'] = outputFile
3498 outputFiles += outputFile
3502 jalviewjsCoreClasslists.each { cl ->
3503 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3506 inputs.file(inputFile)
3507 outputs.files(outputFiles)
3511 task jalviewjsSyncCore (type: Sync) {
3512 dependsOn jalviewjsBuildAllCores
3513 dependsOn jalviewjsPublishCoreTemplates
3514 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3515 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3519 def outputFiles = []
3520 rename { filename ->
3521 outputFiles += "${outputDir}/${filename}"
3527 outputs.files outputFiles
3528 inputs.files inputFiles
3532 // this Copy version of TransferSiteJs will delete anything else in the target dir
3533 task jalviewjsCopyTransferSiteJs(type: Copy) {
3534 dependsOn jalviewjsTranspile
3535 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3536 into "${jalviewDir}/${jalviewjsSiteDir}"
3540 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3541 task jalviewjsSyncTransferSiteJs(type: Sync) {
3542 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3544 into "${jalviewDir}/${jalviewjsSiteDir}"
3551 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3552 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3553 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3554 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3556 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3557 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3558 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3559 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3562 task jalviewjsPrepareSite {
3564 description "Prepares the website folder including unzipping files and copying resources"
3565 dependsOn jalviewjsSyncAllLibs
3566 dependsOn jalviewjsSyncResources
3567 dependsOn jalviewjsSyncSiteResources
3568 dependsOn jalviewjsSyncBuildProperties
3569 dependsOn jalviewjsSyncCore
3573 task jalviewjsBuildSite {
3575 description "Builds the whole website including transpiled code"
3576 dependsOn jalviewjsCopyTransferSiteJs
3577 dependsOn jalviewjsPrepareSite
3581 task cleanJalviewjsTransferSite {
3583 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3584 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3585 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3586 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3591 task cleanJalviewjsSite {
3592 dependsOn cleanJalviewjsTransferSite
3594 delete "${jalviewDir}/${jalviewjsSiteDir}"
3599 task jalviewjsSiteTar(type: Tar) {
3601 description "Creates a tar.gz file for the website"
3602 dependsOn jalviewjsBuildSite
3603 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3604 archiveFileName = outputFilename
3606 compression Compression.GZIP
3608 from "${jalviewDir}/${jalviewjsSiteDir}"
3609 into jalviewjs_site_dir // this is inside the tar file
3611 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3615 task jalviewjsServer {
3617 def filename = "jalviewjsTest.html"
3618 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3619 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3624 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3625 factory = f.newInstance()
3626 } catch (ClassNotFoundException e) {
3627 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3629 def port = Integer.valueOf(jalviewjs_server_port)
3634 while(port < start+1000 && !running) {
3636 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3637 jalviewjsServer = factory.start(doc_root, port)
3639 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3640 println("SERVER STARTED with document root ${doc_root}.")
3641 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3642 println("For debug: "+url+"?j2sdebug")
3643 println("For verbose: "+url+"?j2sverbose")
3644 } catch (Exception e) {
3649 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3650 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3651 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3653 jalviewjsCoreClasslists.each { cl ->
3654 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3656 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3658 println("For core ${cl.name}: "+urlcore)
3661 file(htmlFile).text = htmlText
3664 outputs.file(htmlFile)
3665 outputs.upToDateWhen({false})
3669 task cleanJalviewjsAll {
3671 description "Delete all configuration and build artifacts to do with JalviewJS build"
3672 dependsOn cleanJalviewjsSite
3673 dependsOn jalviewjsEclipsePaths
3676 delete "${jalviewDir}/${jalviewjsBuildDir}"
3677 delete "${jalviewDir}/${eclipse_bin_dir}"
3678 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3679 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3681 delete jalviewjsJ2sAltSettingsFileName
3684 outputs.upToDateWhen( { false } )
3688 task jalviewjsIDE_checkJ2sPlugin {
3689 group "00 JalviewJS in Eclipse"
3690 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3693 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3694 def j2sPluginFile = file(j2sPlugin)
3695 def eclipseHome = System.properties["eclipse.home.location"]
3696 if (eclipseHome == null || ! IN_ECLIPSE) {
3697 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3699 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3700 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3701 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3702 eclipseJ2sPluginDirs += altPluginsDir
3704 def foundPlugin = false
3705 def j2sPluginFileName = j2sPluginFile.getName()
3706 def eclipseJ2sPlugin
3707 def eclipseJ2sPluginFile
3708 eclipseJ2sPluginDirs.any { dir ->
3709 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3710 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3711 if (eclipseJ2sPluginFile.exists()) {
3717 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3718 System.err.println(msg)
3719 throw new StopExecutionException(msg)
3722 def digest = MessageDigest.getInstance("MD5")
3724 digest.update(j2sPluginFile.text.bytes)
3725 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3727 digest.update(eclipseJ2sPluginFile.text.bytes)
3728 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3730 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3731 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3732 System.err.println(msg)
3733 throw new StopExecutionException(msg)
3735 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3741 task jalviewjsIDE_copyJ2sPlugin {
3742 group "00 JalviewJS in Eclipse"
3743 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3746 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3747 def j2sPluginFile = file(j2sPlugin)
3748 def eclipseHome = System.properties["eclipse.home.location"]
3749 if (eclipseHome == null || ! IN_ECLIPSE) {
3750 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3752 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3753 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3754 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3755 System.err.println(msg)
3758 eclipseJ2sPluginFile.getParentFile().mkdirs()
3759 into eclipseJ2sPluginFile.getParent()
3765 task jalviewjsIDE_j2sFile {
3766 group "00 JalviewJS in Eclipse"
3767 description "Creates the .j2s file"
3768 dependsOn jalviewjsCreateJ2sSettings
3772 task jalviewjsIDE_SyncCore {
3773 group "00 JalviewJS in Eclipse"
3774 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3775 dependsOn jalviewjsSyncCore
3779 task jalviewjsIDE_SyncSiteAll {
3780 dependsOn jalviewjsSyncAllLibs
3781 dependsOn jalviewjsSyncResources
3782 dependsOn jalviewjsSyncSiteResources
3783 dependsOn jalviewjsSyncBuildProperties
3787 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3790 task jalviewjsIDE_PrepareSite {
3791 group "00 JalviewJS in Eclipse"
3792 description "Sync libs and resources to site dir, but not closure cores"
3794 dependsOn jalviewjsIDE_SyncSiteAll
3795 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3799 task jalviewjsIDE_AssembleSite {
3800 group "00 JalviewJS in Eclipse"
3801 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3802 dependsOn jalviewjsPrepareSite
3806 task jalviewjsIDE_SiteClean {
3807 group "00 JalviewJS in Eclipse"
3808 description "Deletes the Eclipse transpiled site"
3809 dependsOn cleanJalviewjsSite
3813 task jalviewjsIDE_Server {
3814 group "00 JalviewJS in Eclipse"
3815 description "Starts a webserver on localhost to test the website"
3816 dependsOn jalviewjsServer
3820 // buildship runs this at import or gradle refresh
3821 task eclipseSynchronizationTask {
3822 //dependsOn eclipseSetup
3823 dependsOn createBuildProperties
3825 dependsOn jalviewjsIDE_j2sFile
3826 dependsOn jalviewjsIDE_checkJ2sPlugin
3827 dependsOn jalviewjsIDE_PrepareSite
3832 // buildship runs this at build time or project refresh
3833 task eclipseAutoBuildTask {
3834 //dependsOn jalviewjsIDE_checkJ2sPlugin
3835 //dependsOn jalviewjsIDE_PrepareSite
3841 description "Build the site"
3842 dependsOn jalviewjsBuildSite