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 java.util.regex.Matcher
13 import groovy.transform.ExternalizeMethods
14 import groovy.util.XmlParser
15 import groovy.xml.XmlUtil
16 import groovy.json.JsonBuilder
17 import com.vladsch.flexmark.util.ast.Node
18 import com.vladsch.flexmark.html.HtmlRenderer
19 import com.vladsch.flexmark.parser.Parser
20 import com.vladsch.flexmark.util.data.MutableDataSet
21 import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension
22 import com.vladsch.flexmark.ext.tables.TablesExtension
23 import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension
24 import com.vladsch.flexmark.ext.autolink.AutolinkExtension
25 import com.vladsch.flexmark.ext.anchorlink.AnchorLinkExtension
26 import com.vladsch.flexmark.ext.toc.TocExtension
27 import com.google.common.hash.HashCode
28 import com.google.common.hash.Hashing
29 import com.google.common.io.Files
30 import org.jsoup.Jsoup
31 import org.jsoup.nodes.Element
39 classpath "com.vladsch.flexmark:flexmark-all:0.62.0"
40 classpath "org.jsoup:jsoup:1.14.3"
41 classpath "com.eowise:gradle-imagemagick:0.5.1"
50 id "com.diffplug.gradle.spotless" version "3.28.0"
51 id 'com.github.johnrengelman.shadow' version '4.0.3'
52 id 'com.install4j.gradle' version '9.0.6'
53 id 'com.dorongold.task-tree' version '2.1.0' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
54 id 'com.palantir.git-version' version '0.13.0' apply false
65 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
66 def string(Object o) {
67 return o == null ? "" : o.toString()
70 def overrideProperties(String propsFileName, boolean output = false) {
71 if (propsFileName == null) {
74 def propsFile = file(propsFileName)
75 if (propsFile != null && propsFile.exists()) {
76 println("Using properties from file '${propsFileName}'")
78 def p = new Properties()
79 def localPropsFIS = new FileInputStream(propsFile)
85 if (project.hasProperty(key)) {
86 oldval = project.findProperty(key)
87 project.setProperty(key, val)
89 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
92 ext.setProperty(key, val)
94 println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'")
98 } catch (Exception e) {
99 println("Exception reading local.properties")
106 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
107 jalviewDirRelativePath = jalviewDir
110 getdownChannelName = CHANNEL.toLowerCase()
111 // default to "default". Currently only has different cosmetics for "develop", "release", "default"
112 propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default"
113 channelDirName = propertiesChannelName
114 // Import channel_properties
115 if (getdownChannelName.startsWith("develop-")) {
116 channelDirName = "develop-SUFFIX"
118 channelDir = string("${jalviewDir}/${channel_properties_dir}/${channelDirName}")
119 channelGradleProperties = string("${channelDir}/channel_gradle.properties")
120 channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}")
121 overrideProperties(channelGradleProperties, false)
122 // local build environment properties
123 // can be "projectDir/local.properties"
124 overrideProperties("${projectDir}/local.properties", true)
125 // or "../projectDir_local.properties"
126 overrideProperties(projectDir.getParent() + "/" + projectDir.getName() + "_local.properties", true)
129 // Import releaseProps from the RELEASE file
130 // or a file specified via JALVIEW_RELEASE_FILE if defined
131 // Expect jalview.version and target release branch in jalview.release
132 releaseProps = new Properties();
133 def releasePropFile = findProperty("JALVIEW_RELEASE_FILE");
134 def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE";
136 (new File(releasePropFile!=null ? releasePropFile : defaultReleasePropFile)).withInputStream {
137 releaseProps.load(it)
139 } catch (Exception fileLoadError) {
140 throw new Error("Couldn't load release properties file "+(releasePropFile==null ? defaultReleasePropFile : "from custom location: releasePropFile"),fileLoadError);
143 // Set JALVIEW_VERSION if it is not already set
144 if (findProperty("JALVIEW_VERSION")==null || "".equals(JALVIEW_VERSION)) {
145 JALVIEW_VERSION = releaseProps.get("jalview.version")
147 println("JALVIEW_VERSION is set to '${JALVIEW_VERSION}'")
149 // this property set when running Eclipse headlessly
150 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
151 // this property set by Eclipse
152 eclipseApplicationProperty = string("eclipse.application")
153 // CHECK IF RUNNING FROM WITHIN ECLIPSE
154 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
155 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
156 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
157 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
158 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
162 println("WITHIN ECLIPSE IDE")
164 println("HEADLESS BUILD")
167 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
169 println("J2S ENABLED")
172 System.properties.sort { it.key }.each {
173 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
176 if (false && IN_ECLIPSE) {
177 jalviewDir = jalviewDirAbsolutePath
182 buildDate = new Date().format("yyyyMMdd")
185 bareSourceDir = string(source_dir)
186 sourceDir = string("${jalviewDir}/${bareSourceDir}")
187 resourceDir = string("${jalviewDir}/${resource_dir}")
188 bareTestSourceDir = string(test_source_dir)
189 testDir = string("${jalviewDir}/${bareTestSourceDir}")
191 classesDir = string("${jalviewDir}/${classes_dir}")
194 useClover = clover.equals("true")
195 cloverBuildDir = "${buildDir}/clover"
196 cloverInstrDir = file("${cloverBuildDir}/clover-instr")
197 cloverClassesDir = file("${cloverBuildDir}/clover-classes")
198 cloverReportDir = file("${buildDir}/reports/clover")
199 cloverTestInstrDir = file("${cloverBuildDir}/clover-test-instr")
200 cloverTestClassesDir = file("${cloverBuildDir}/clover-test-classes")
201 //cloverTestClassesDir = cloverClassesDir
202 cloverDb = string("${cloverBuildDir}/clover.db")
204 testSourceDir = useClover ? cloverTestInstrDir : testDir
205 testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}"
208 backgroundImageText = BACKGROUNDIMAGETEXT
209 getdownChannelDir = string("${getdown_website_dir}/${propertiesChannelName}")
210 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
211 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
212 getdownFullArchiveDir = null
213 getdownTextLines = []
214 getdownLaunchJvl = null
215 getdownVersionLaunchJvl = null
217 buildProperties = null
219 // the following values might be overridden by the CHANNEL switch
220 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
221 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
222 getdownArchiveAppBase = getdown_archive_base
223 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
224 getdownAppDistDir = getdown_app_dir_alt
225 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
226 getdownImagesBuildDir = string("${buildDir}/imagemagick/getdown")
227 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
228 reportRsyncCommand = false
229 jvlChannelName = CHANNEL.toLowerCase()
230 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
231 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
232 install4jDMGBackgroundImageDir = "${install4j_images_dir}"
233 install4jDMGBackgroundImageBuildDir = "build/imagemagick/install4j"
234 install4jDMGBackgroundImageFile = "${install4j_dmg_background}"
235 install4jInstallerName = "${jalview_name} Non-Release Installer"
236 install4jExecutableName = install4j_executable_name
237 install4jExtraScheme = "jalviewx"
238 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
239 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
240 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
241 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
242 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
243 install4jCheckSums = true
245 applicationName = "${jalview_name}"
249 // TODO: get bamboo build artifact URL for getdown artifacts
250 getdown_channel_base = bamboo_channelbase
251 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
252 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
253 jvlChannelName += "_${getdownChannelName}"
254 // automatically add the test group Not-bamboo for exclusion
255 if ("".equals(testng_excluded_groups)) {
256 testng_excluded_groups = "Not-bamboo"
258 install4jExtraScheme = "jalviewb"
259 backgroundImageText = true
262 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
263 getdownAppDistDir = getdown_app_dir_release
264 getdownSetAppBaseProperty = true
265 reportRsyncCommand = true
267 install4jInstallerName = "${jalview_name} Installer"
271 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
272 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
273 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
274 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
275 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
277 package_dir = string("${ARCHIVEDIR}/${package_dir}")
278 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
281 reportRsyncCommand = true
282 install4jExtraScheme = "jalviewa"
286 getdownChannelName = string("archive/${JALVIEW_VERSION}")
287 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
288 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
289 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
290 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution [did not find '${ARCHIVEDIR}/${package_dir}']")
292 package_dir = string("${ARCHIVEDIR}/${package_dir}")
293 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
296 reportRsyncCommand = true
297 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
298 install4jSuffix = "Archive"
299 install4jExtraScheme = "jalviewa"
302 case ~/^DEVELOP-([\.\-\w]*)$/:
303 def suffix = Matcher.lastMatcher[0][1]
304 reportRsyncCommand = true
305 getdownSetAppBaseProperty = true
306 JALVIEW_VERSION=JALVIEW_VERSION+"-d${suffix}-${buildDate}"
307 install4jSuffix = "Develop ${suffix}"
308 install4jExtraScheme = "jalviewd"
309 install4jInstallerName = "${jalview_name} Develop ${suffix} Installer"
310 getdownChannelName = string("develop-${suffix}")
311 getdownChannelDir = string("${getdown_website_dir}/${getdownChannelName}")
312 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
313 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
314 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
315 channelSuffix = string(suffix)
316 backgroundImageText = true
320 reportRsyncCommand = true
321 getdownSetAppBaseProperty = true
322 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
323 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
325 install4jSuffix = "Develop"
326 install4jExtraScheme = "jalviewd"
327 install4jInstallerName = "${jalview_name} Develop Installer"
328 backgroundImageText = true
332 reportRsyncCommand = true
333 getdownSetAppBaseProperty = true
334 // Don't ignore transpile errors for release build
335 if (jalviewjs_ignore_transpile_errors.equals("true")) {
336 jalviewjs_ignore_transpile_errors = "false"
337 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
339 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
340 install4jSuffix = "Test"
341 install4jExtraScheme = "jalviewt"
342 install4jInstallerName = "${jalview_name} Test Installer"
343 backgroundImageText = true
346 case ~/^SCRATCH(|-[-\w]*)$/:
347 getdownChannelName = CHANNEL
348 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
350 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
351 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
352 reportRsyncCommand = true
353 install4jSuffix = "Scratch"
357 if (!file("${LOCALDIR}").exists()) {
358 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
360 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
361 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
363 JALVIEW_VERSION = "TEST"
364 install4jSuffix = "Test-Local"
365 install4jExtraScheme = "jalviewt"
366 install4jInstallerName = "${jalview_name} Test Installer"
367 backgroundImageText = true
370 case [ "LOCAL", "JALVIEWJS" ]:
371 JALVIEW_VERSION = "TEST"
372 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
373 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
374 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
375 install4jExtraScheme = "jalviewl"
376 install4jCheckSums = false
379 default: // something wrong specified
380 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
384 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
385 hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_data_installers_dir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
386 hugoArchiveMdFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_version_archive_dir}/Version-${JALVIEW_VERSION_UNDERSCORES}/_index.md")
387 // override getdownAppBase if requested
388 if (findProperty("getdown_appbase_override") != null) {
389 // revert to LOCAL if empty string
390 if (string(getdown_appbase_override) == "") {
391 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
392 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
393 } else if (string(getdown_appbase_override).startsWith("file://")) {
394 getdownAppBase = string(getdown_appbase_override)
395 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
397 getdownAppBase = string(getdown_appbase_override)
399 println("Overriding getdown appbase with '${getdownAppBase}'")
401 // sanitise file name for jalview launcher file for this channel
402 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
403 // install4j application and folder names
404 if (install4jSuffix == "") {
405 install4jBundleId = "${install4j_bundle_id}"
406 install4jWinApplicationId = install4j_release_win_application_id
408 applicationName = "${jalview_name} ${install4jSuffix}"
409 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
410 // add int hash of install4jSuffix to the last part of the application_id
411 def id = install4j_release_win_application_id
412 def idsplitreverse = id.split("-").reverse()
413 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
414 install4jWinApplicationId = idsplitreverse.reverse().join("-")
416 // sanitise folder and id names
417 // install4jApplicationFolder = e.g. "Jalview Build"
418 install4jApplicationFolder = applicationName
419 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
420 .replaceAll("_+", "_") // collapse __
421 install4jInternalId = applicationName
423 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
424 .replaceAll("_+", "") // collapse __
425 //.replaceAll("_*-_*", "-") // collapse _-_
426 install4jUnixApplicationFolder = applicationName
428 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
429 .replaceAll("_+", "_") // collapse __
430 .replaceAll("_*-_*", "-") // collapse _-_
433 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
434 getdownAppDir = string("${getdownAppBaseDir}/${getdownAppDistDir}")
435 //getdownJ11libDir = "${getdownAppBaseDir}/${getdown_j11lib_dir}"
436 getdownResourceDir = string("${getdownAppBaseDir}/${getdown_resource_dir}")
437 getdownInstallDir = string("${getdownAppBaseDir}/${getdown_install_dir}")
438 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
439 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
440 /* compile without modules -- using classpath libraries
441 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
442 modules_runtimeClasspath = modules_compileClasspath
448 apply plugin: "com.palantir.git-version"
449 def details = versionDetails()
450 gitHash = details.gitHash
451 gitBranch = details.branchName
452 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
453 println("Not in a git repository. Using git values from RELEASE properties file.")
454 gitHash = releaseProps.getProperty("git.hash")
455 gitBranch = releaseProps.getProperty("git.branch")
456 } catch(java.lang.RuntimeException e1) {
457 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
460 println("Using a ${CHANNEL} profile.")
462 additional_compiler_args = []
463 // configure classpath/args for j8/j11 compilation
464 if (JAVA_VERSION.equals("1.8")) {
465 JAVA_INTEGER_VERSION = string("8")
468 libDistDir = j8libDir
469 compile_source_compatibility = 1.8
470 compile_target_compatibility = 1.8
471 // these are getdown.txt properties defined dependent on the JAVA_VERSION
472 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
473 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
474 // this property is assigned below and expanded to multiple lines in the getdown task
475 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
476 // this property is for the Java library used in eclipse
477 eclipseJavaRuntimeName = string("JavaSE-1.8")
478 } else if (JAVA_VERSION.equals("11")) {
479 JAVA_INTEGER_VERSION = string("11")
481 libDistDir = j11libDir
482 compile_source_compatibility = 11
483 compile_target_compatibility = 11
484 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
485 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
486 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
487 eclipseJavaRuntimeName = string("JavaSE-11")
488 /* compile without modules -- using classpath libraries
489 additional_compiler_args += [
490 '--module-path', modules_compileClasspath.asPath,
491 '--add-modules', j11modules
494 } else if (JAVA_VERSION.equals("17")) {
495 JAVA_INTEGER_VERSION = string("17")
497 libDistDir = j17libDir
498 compile_source_compatibility = 17
499 compile_target_compatibility = 17
500 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
501 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
502 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
503 eclipseJavaRuntimeName = string("JavaSE-17")
504 /* compile without modules -- using classpath libraries
505 additional_compiler_args += [
506 '--module-path', modules_compileClasspath.asPath,
507 '--add-modules', j11modules
511 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
516 JAVA_MIN_VERSION = JAVA_VERSION
517 JAVA_MAX_VERSION = JAVA_VERSION
518 def jreInstallsDir = string(jre_installs_dir)
519 if (jreInstallsDir.startsWith("~/")) {
520 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
522 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
523 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
524 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
525 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
526 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
527 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
528 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
529 install4jConfFileName = string("jalview-install4j-conf.install4j")
530 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
531 install4jHomeDir = install4j_home_dir
532 if (install4jHomeDir.startsWith("~/")) {
533 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
536 resourceBuildDir = string("${buildDir}/resources")
537 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
538 helpBuildDir = string("${resourceBuildDir}/help_build")
539 docBuildDir = string("${resourceBuildDir}/doc_build")
541 if (buildProperties == null) {
542 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
544 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
545 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
546 helpSourceDir = string("${helpParentDir}/${help_dir}")
547 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
550 convertBinaryExpectedLocation = imagemagick_convert
551 if (convertBinaryExpectedLocation.startsWith("~/")) {
552 convertBinaryExpectedLocation = System.getProperty("user.home") + convertBinaryExpectedLocation.substring(1)
554 if (file(convertBinaryExpectedLocation).exists()) {
555 convertBinary = convertBinaryExpectedLocation
558 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
559 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
560 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
562 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
564 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
566 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
567 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
568 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
569 jalviewjsJalviewCoreHtmlFile = string("")
570 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
571 jalviewjsCoreClasslists = []
572 jalviewjsJalviewTemplateName = string(jalviewjs_name)
573 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
574 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
575 jalviewjsJ2sProps = null
576 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
578 eclipseWorkspace = null
579 eclipseBinary = string("")
580 eclipseVersion = string("")
590 outputDir = file(classesDir)
594 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
597 compileClasspath = files(sourceSets.main.java.outputDir)
598 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
600 runtimeClasspath = compileClasspath
601 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
606 srcDirs cloverInstrDir
607 outputDir = cloverClassesDir
611 srcDirs = sourceSets.main.resources.srcDirs
614 compileClasspath = files( sourceSets.clover.java.outputDir )
615 //compileClasspath += files( testClassesDir )
616 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
617 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
618 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
620 runtimeClasspath = compileClasspath
625 srcDirs testSourceDir
626 outputDir = file(testClassesDir)
630 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
633 compileClasspath = files( sourceSets.test.java.outputDir )
634 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
635 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
637 runtimeClasspath = compileClasspath
638 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
644 // eclipse project and settings files creation, also used by buildship
647 name = eclipse_project_name
649 natures 'org.eclipse.jdt.core.javanature',
650 'org.eclipse.jdt.groovy.core.groovyNature',
651 'org.eclipse.buildship.core.gradleprojectnature'
653 buildCommand 'org.eclipse.jdt.core.javabuilder'
654 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
658 //defaultOutputDir = sourceSets.main.java.outputDir
659 configurations.each{ c->
660 if (c.isCanBeResolved()) {
661 minusConfigurations += [c]
665 plusConfigurations = [ ]
669 def removeTheseToo = []
670 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
671 cp.entries.each { entry ->
672 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
673 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
674 // we add the resources and help/help dirs in as libs afterwards (see below)
675 if (entry.kind == 'src') {
676 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
677 removeTheseToo += entry
679 alreadyAddedSrcPath.putAt(entry.path, true)
684 cp.entries.removeAll(removeTheseToo)
686 //cp.entries += new Output("${eclipse_bin_dir}/main")
687 if (file(helpParentDir).isDirectory()) {
688 cp.entries += new Library(fileReference(helpParentDir))
690 if (file(resourceDir).isDirectory()) {
691 cp.entries += new Library(fileReference(resourceDir))
694 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
696 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
697 //don't want to add outputDir as eclipse is using its own output dir in bin/main
698 if (it.isDirectory() || ! it.exists()) {
699 // don't add dirs to classpath, especially if they don't exist
700 return false // groovy "continue" in .any closure
702 def itPath = it.toString()
703 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
704 // make relative path
705 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
707 if (alreadyAddedLibPath.get(itPath)) {
708 //println("Not adding duplicate entry "+itPath)
710 //println("Adding entry "+itPath)
711 cp.entries += new Library(fileReference(itPath))
712 alreadyAddedLibPath.put(itPath, true)
716 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
717 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
718 if (it.isDirectory() || ! it.exists()) {
719 // don't add dirs to classpath
720 return false // groovy "continue" in .any closure
723 def itPath = it.toString()
724 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
725 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
727 if (alreadyAddedLibPath.get(itPath)) {
730 def lib = new Library(fileReference(itPath))
731 lib.entryAttributes["test"] = "true"
733 alreadyAddedLibPath.put(itPath, true)
741 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
746 // for the IDE, use java 11 compatibility
747 sourceCompatibility = compile_source_compatibility
748 targetCompatibility = compile_target_compatibility
749 javaRuntimeName = eclipseJavaRuntimeName
751 // add in jalview project specific properties/preferences into eclipse core preferences
753 withProperties { props ->
754 def jalview_prefs = new Properties()
755 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
756 jalview_prefs.load(ins)
758 jalview_prefs.forEach { t, v ->
759 if (props.getAt(t) == null) {
763 // codestyle file -- overrides previous formatter prefs
764 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
765 if (csFile.exists()) {
766 XmlParser parser = new XmlParser()
767 def profiles = parser.parse(csFile)
768 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
769 if (profile != null) {
770 profile.'setting'.each { s ->
772 def value = s.'@value'
773 if (id != null && value != null) {
774 props.putAt(id, value)
785 // Don't want these to be activated if in headless build
786 synchronizationTasks "eclipseSynchronizationTask"
787 //autoBuildTasks "eclipseAutoBuildTask"
793 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
794 // Class to allow updating arbitrary properties files
795 class PropertiesFile extends PropertiesPersistableConfigurationObject {
796 public PropertiesFile(PropertiesTransformer t) { super(t); }
797 @Override protected void load(Properties properties) { }
798 @Override protected void store(Properties properties) { }
799 @Override protected String getDefaultResourceName() { return ""; }
800 // This is necessary, because PropertiesPersistableConfigurationObject fails
801 // if no default properties file exists.
802 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
805 // Task to update arbitrary properties files (set outputFile)
806 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
807 private final PropertiesFileContentMerger file;
808 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
809 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
810 protected void configure(PropertiesFile props) {
811 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
813 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
816 task eclipseUIPreferences(type: PropertiesFileTask) {
817 description = "Generate Eclipse additional settings"
818 def filename = "org.eclipse.jdt.ui.prefs"
819 outputFile = "$projectDir/.settings/${filename}" as File
822 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
827 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
828 description = "Generate Eclipse additional settings"
829 def filename = "org.eclipse.jdt.groovy.core.prefs"
830 outputFile = "$projectDir/.settings/${filename}" as File
833 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
838 task eclipseAllPreferences {
840 dependsOn eclipseUIPreferences
841 dependsOn eclipseGroovyCorePreferences
844 eclipseUIPreferences.mustRunAfter eclipseJdt
845 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
847 /* end of eclipse preferences hack */
855 delete cloverBuildDir
856 delete cloverReportDir
861 task cloverInstrJava(type: JavaExec) {
862 group = "Verification"
863 description = "Create clover instrumented source java files"
865 dependsOn cleanClover
867 inputs.files(sourceSets.main.allJava)
868 outputs.dir(cloverInstrDir)
870 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
871 classpath = sourceSets.clover.compileClasspath
872 main = "com.atlassian.clover.CloverInstr"
880 cloverInstrDir.getPath(),
882 def srcFiles = sourceSets.main.allJava.files
885 { file -> file.absolutePath }
888 args argsList.toArray()
891 delete cloverInstrDir
892 println("Clover: About to instrument "+srcFiles.size() +" files")
897 task cloverInstrTests(type: JavaExec) {
898 group = "Verification"
899 description = "Create clover instrumented source test files"
901 dependsOn cleanClover
903 inputs.files(testDir)
904 outputs.dir(cloverTestInstrDir)
906 classpath = sourceSets.clover.compileClasspath
907 main = "com.atlassian.clover.CloverInstr"
917 cloverTestInstrDir.getPath(),
919 args argsList.toArray()
922 delete cloverTestInstrDir
923 println("Clover: About to instrument test files")
929 group = "Verification"
930 description = "Create clover instrumented all source files"
932 dependsOn cloverInstrJava
933 dependsOn cloverInstrTests
937 cloverClasses.dependsOn cloverInstr
940 task cloverConsoleReport(type: JavaExec) {
941 group = "Verification"
942 description = "Creates clover console report"
945 file(cloverDb).exists()
948 inputs.dir cloverClassesDir
950 classpath = sourceSets.clover.runtimeClasspath
951 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
953 if (cloverreport_mem.length() > 0) {
954 maxHeapSize = cloverreport_mem
956 if (cloverreport_jvmargs.length() > 0) {
957 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
967 args argsList.toArray()
971 task cloverHtmlReport(type: JavaExec) {
972 group = "Verification"
973 description = "Creates clover HTML report"
976 file(cloverDb).exists()
979 def cloverHtmlDir = cloverReportDir
980 inputs.dir cloverClassesDir
981 outputs.dir cloverHtmlDir
983 classpath = sourceSets.clover.runtimeClasspath
984 main = "com.atlassian.clover.reporters.html.HtmlReporter"
986 if (cloverreport_mem.length() > 0) {
987 maxHeapSize = cloverreport_mem
989 if (cloverreport_jvmargs.length() > 0) {
990 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
1001 if (cloverreport_html_options.length() > 0) {
1002 argsList += cloverreport_html_options.split(" ")
1005 args argsList.toArray()
1009 task cloverXmlReport(type: JavaExec) {
1010 group = "Verification"
1011 description = "Creates clover XML report"
1014 file(cloverDb).exists()
1017 def cloverXmlFile = "${cloverReportDir}/clover.xml"
1018 inputs.dir cloverClassesDir
1019 outputs.file cloverXmlFile
1021 classpath = sourceSets.clover.runtimeClasspath
1022 main = "com.atlassian.clover.reporters.xml.XMLReporter"
1024 if (cloverreport_mem.length() > 0) {
1025 maxHeapSize = cloverreport_mem
1027 if (cloverreport_jvmargs.length() > 0) {
1028 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
1039 if (cloverreport_xml_options.length() > 0) {
1040 argsList += cloverreport_xml_options.split(" ")
1043 args argsList.toArray()
1048 group = "Verification"
1049 description = "Creates clover reports"
1051 dependsOn cloverXmlReport
1052 dependsOn cloverHtmlReport
1059 sourceCompatibility = compile_source_compatibility
1060 targetCompatibility = compile_target_compatibility
1061 options.compilerArgs += additional_compiler_args
1062 print ("Setting target compatibility to "+targetCompatibility+"\n")
1064 //classpath += configurations.cloverRuntime
1070 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1071 sourceCompatibility = compile_source_compatibility
1072 targetCompatibility = compile_target_compatibility
1073 options.compilerArgs = additional_compiler_args
1074 options.encoding = "UTF-8"
1076 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1083 sourceCompatibility = compile_source_compatibility
1084 targetCompatibility = compile_target_compatibility
1085 options.compilerArgs = additional_compiler_args
1087 print ("Setting target compatibility to "+targetCompatibility+"\n")
1094 delete sourceSets.main.java.outputDir
1100 dependsOn cleanClover
1102 delete sourceSets.test.java.outputDir
1107 // format is a string like date.format("dd MMMM yyyy")
1108 def getDate(format) {
1109 return date.format(format)
1113 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1114 MutableDataSet options = new MutableDataSet()
1116 def extensions = new ArrayList<>()
1117 extensions.add(AnchorLinkExtension.create())
1118 extensions.add(AutolinkExtension.create())
1119 extensions.add(StrikethroughExtension.create())
1120 extensions.add(TaskListExtension.create())
1121 extensions.add(TablesExtension.create())
1122 extensions.add(TocExtension.create())
1124 options.set(Parser.EXTENSIONS, extensions)
1126 // set GFM table parsing options
1127 options.set(TablesExtension.WITH_CAPTION, false)
1128 options.set(TablesExtension.COLUMN_SPANS, false)
1129 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1130 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1131 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1132 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1133 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1135 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1136 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1137 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1138 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1140 Parser parser = Parser.builder(options).build()
1141 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1143 mdFiles.each { mdFile ->
1144 // add table of contents
1145 def mdText = "[TOC]\n"+mdFile.text
1147 // grab the first top-level title
1149 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1150 def matcher = mdText =~ titleRegex
1151 if (matcher.size() > 0) {
1152 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1153 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1155 // or use the filename if none found
1156 if (title == null) {
1157 title = mdFile.getName()
1160 Node document = parser.parse(mdText)
1161 String htmlBody = renderer.render(document)
1162 def htmlText = '''<html>
1163 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1164 <html xmlns="http://www.w3.org/1999/xhtml">
1166 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1167 <meta http-equiv="Content-Style-Type" content="text/css" />
1168 <meta name="generator" content="flexmark" />
1170 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1172 <style type="text/css">code{white-space: pre;}</style>
1174 htmlText += ((cssFile != null) ? cssFile.text : '')
1175 htmlText += '''</head>
1178 htmlText += htmlBody
1184 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1185 def htmlFile = file(htmlFilePath)
1186 println("Creating ${htmlFilePath}")
1187 htmlFile.text = htmlText
1192 task copyDocs(type: Copy) {
1193 def inputDir = "${jalviewDir}/${doc_dir}"
1194 def outputDir = "${docBuildDir}/${doc_dir}"
1198 include('**/*.html')
1200 filter(ReplaceTokens,
1204 'Version-Rel': JALVIEW_VERSION,
1205 'Year-Rel': getDate("yyyy")
1212 exclude('**/*.html')
1217 inputs.dir(inputDir)
1218 outputs.dir(outputDir)
1222 task convertMdFiles {
1224 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1225 def cssFile = file("${jalviewDir}/${flexmark_css}")
1228 convertMdToHtml(mdFiles, cssFile)
1231 inputs.files(mdFiles)
1232 inputs.file(cssFile)
1235 mdFiles.each { mdFile ->
1236 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1237 htmlFiles.add(file(htmlFilePath))
1239 outputs.files(htmlFiles)
1243 def hugoTemplateSubstitutions(String input, Map extras=null) {
1244 def replacements = [
1245 DATE: getDate("yyyy-MM-dd"),
1246 CHANNEL: propertiesChannelName,
1247 APPLICATION_NAME: applicationName,
1249 GIT_BRANCH: gitBranch,
1250 VERSION: JALVIEW_VERSION,
1251 JAVA_VERSION: JAVA_VERSION,
1252 VERSION_UNDERSCORES: JALVIEW_VERSION_UNDERSCORES,
1257 if (extras != null) {
1258 extras.each{ k, v ->
1259 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1262 replacements.each{ k, v ->
1263 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1268 def mdFileComponents(File mdFile, def dateOnly=false) {
1271 if (mdFile.exists()) {
1272 def inFrontMatter = false
1273 def firstLine = true
1274 mdFile.eachLine { line ->
1275 if (line.matches("---")) {
1276 def prev = inFrontMatter
1277 inFrontMatter = firstLine
1278 if (inFrontMatter != prev)
1281 if (inFrontMatter) {
1283 if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
1284 map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
1285 } else if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
1286 map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
1287 } else if (m = line =~ /^channel:\s*(\S+)/) {
1288 map["channel"] = m[0][1]
1289 } else if (m = line =~ /^version:\s*(\S+)/) {
1290 map["version"] = m[0][1]
1291 } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
1292 map[ m[0][1] ] = m[0][2]
1294 if (dateOnly && map["date"] != null) {
1300 content += line+"\n"
1305 return dateOnly ? map["date"] : [map, content]
1308 task hugoTemplates {
1310 description "Create partially populated md pages for hugo website build"
1312 def hugoTemplatesDir = file("${jalviewDir}/${hugo_templates_dir}")
1313 def hugoBuildDir = "${jalviewDir}/${hugo_build_dir}"
1314 def templateFiles = fileTree(dir: hugoTemplatesDir)
1315 def releaseMdFile = file("${jalviewDir}/${releases_dir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1316 def whatsnewMdFile = file("${jalviewDir}/${whatsnew_dir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1317 def oldJvlFile = file("${jalviewDir}/${hugo_old_jvl}")
1318 def jalviewjsFile = file("${jalviewDir}/${hugo_jalviewjs}")
1321 // specific release template for version archive
1324 def givenDate = null
1325 def givenChannel = null
1326 def givenVersion = null
1327 if (CHANNEL == "RELEASE") {
1328 def (map, content) = mdFileComponents(releaseMdFile)
1329 givenDate = map.date
1330 givenChannel = map.channel
1331 givenVersion = map.version
1333 if (givenVersion != null && givenVersion != JALVIEW_VERSION) {
1334 throw new GradleException("'version' header (${givenVersion}) found in ${releaseMdFile} does not match JALVIEW_VERSION (${JALVIEW_VERSION})")
1337 if (whatsnewMdFile.exists())
1338 whatsnew = whatsnewMdFile.text
1341 def oldJvl = oldJvlFile.exists() ? oldJvlFile.collect{it} : []
1342 def jalviewjsLink = jalviewjsFile.exists() ? jalviewjsFile.collect{it} : []
1344 def changesHugo = null
1345 if (changes != null) {
1346 changesHugo = '<div class="release_notes">\n\n'
1347 def inSection = false
1348 changes.eachLine { line ->
1350 if (m = line =~ /^##([^#].*)$/) {
1352 changesHugo += "</div>\n\n"
1354 def section = m[0][1].trim()
1355 section = section.toLowerCase()
1356 section = section.replaceAll(/ +/, "_")
1357 section = section.replaceAll(/[^a-z0-9_\-]/, "")
1358 changesHugo += "<div class=\"${section}\">\n\n"
1360 } else if (m = line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
1361 def comment = m[0][2].trim()
1362 if (comment != "") {
1363 comment = comment.replaceAll('"', """)
1365 comment.eachMatch(/JAL-\d+/) { jal -> issuekeys += jal }
1366 def newline = m[0][1]
1367 if (comment.trim() != "")
1368 newline += "{{<comment>}}${comment}{{</comment>}} "
1369 newline += m[0][3].trim()
1370 if (issuekeys.size() > 0)
1371 newline += " {{< jal issue=\"${issuekeys.join(",")}\" alt=\"${comment}\" >}}"
1372 if (m[0][4] != null)
1377 changesHugo += line+"\n"
1380 changesHugo += "\n</div>\n\n"
1382 changesHugo += '</div>'
1385 templateFiles.each{ templateFile ->
1386 def newFileName = string(hugoTemplateSubstitutions(templateFile.getName()))
1387 def relPath = hugoTemplatesDir.toPath().relativize(templateFile.toPath()).getParent()
1388 def newRelPathName = hugoTemplateSubstitutions( relPath.toString() )
1390 def outPathName = string("${hugoBuildDir}/$newRelPathName")
1394 rename(templateFile.getName(), newFileName)
1398 def newFile = file("${outPathName}/${newFileName}".toString())
1399 def content = newFile.text
1400 newFile.text = hugoTemplateSubstitutions(content,
1403 CHANGES: changesHugo,
1404 DATE: givenDate == null ? "" : givenDate.format("yyyy-MM-dd"),
1405 DRAFT: givenDate == null ? "true" : "false",
1406 JALVIEWJSLINK: jalviewjsLink.contains(JALVIEW_VERSION) ? "true" : "false",
1407 JVL_HEADER: oldJvl.contains(JALVIEW_VERSION) ? "jvl: true" : ""
1414 inputs.file(oldJvlFile)
1415 inputs.dir(hugoTemplatesDir)
1416 inputs.property("JALVIEW_VERSION", { JALVIEW_VERSION })
1417 inputs.property("CHANNEL", { CHANNEL })
1420 def getMdDate(File mdFile) {
1421 return mdFileComponents(mdFile, true)
1424 def getMdSections(String content) {
1426 def sectionContent = ""
1427 def sectionName = null
1428 content.eachLine { line ->
1430 if (m = line =~ /^##([^#].*)$/) {
1431 if (sectionName != null) {
1432 sections[sectionName] = sectionContent
1436 sectionName = m[0][1].trim()
1437 sectionName = sectionName.toLowerCase()
1438 sectionName = sectionName.replaceAll(/ +/, "_")
1439 sectionName = sectionName.replaceAll(/[^a-z0-9_\-]/, "")
1440 } else if (sectionName != null) {
1441 sectionContent += line+"\n"
1444 if (sectionContent != null) {
1445 sections[sectionName] = sectionContent
1451 task copyHelp(type: Copy) {
1452 def inputDir = helpSourceDir
1453 def outputDir = "${helpBuildDir}/${help_dir}"
1457 include('**/*.html')
1461 filter(ReplaceTokens,
1465 'Version-Rel': JALVIEW_VERSION,
1466 'Year-Rel': getDate("yyyy")
1473 exclude('**/*.html')
1480 inputs.dir(inputDir)
1481 outputs.files(helpFile)
1482 outputs.dir(outputDir)
1486 task releasesTemplates {
1488 description "Recreate whatsNew.html and releases.html from markdown files and templates in help"
1492 def releasesTemplateFile = file("${jalviewDir}/${releases_template}")
1493 def whatsnewTemplateFile = file("${jalviewDir}/${whatsnew_template}")
1494 def releasesHtmlFile = file("${helpBuildDir}/${help_dir}/${releases_html}")
1495 def whatsnewHtmlFile = file("${helpBuildDir}/${help_dir}/${whatsnew_html}")
1496 def releasesMdDir = "${jalviewDir}/${releases_dir}"
1497 def whatsnewMdDir = "${jalviewDir}/${whatsnew_dir}"
1500 def releaseMdFile = file("${releasesMdDir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1501 def whatsnewMdFile = file("${whatsnewMdDir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1503 if (CHANNEL == "RELEASE") {
1504 if (!releaseMdFile.exists()) {
1505 throw new GradleException("File ${releaseMdFile} must be created for RELEASE")
1507 if (!whatsnewMdFile.exists()) {
1508 throw new GradleException("File ${whatsnewMdFile} must be created for RELEASE")
1512 def releaseFiles = fileTree(dir: releasesMdDir, include: "release-*.md")
1513 def releaseFilesDates = releaseFiles.collectEntries {
1514 [(it): getMdDate(it)]
1516 releaseFiles = releaseFiles.sort { a,b -> releaseFilesDates[a].compareTo(releaseFilesDates[b]) }
1518 def releasesTemplate = releasesTemplateFile.text
1519 def m = releasesTemplate =~ /(?s)__VERSION_LOOP_START__(.*)__VERSION_LOOP_END__/
1520 def versionTemplate = m[0][1]
1522 MutableDataSet options = new MutableDataSet()
1524 def extensions = new ArrayList<>()
1525 options.set(Parser.EXTENSIONS, extensions)
1526 options.set(Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE, true)
1528 Parser parser = Parser.builder(options).build()
1529 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1531 def actualVersions = releaseFiles.collect { rf ->
1532 def (rfMap, rfContent) = mdFileComponents(rf)
1533 return rfMap.version
1535 def versionsHtml = ""
1536 def linkedVersions = []
1537 releaseFiles.reverse().each { rFile ->
1538 def (rMap, rContent) = mdFileComponents(rFile)
1540 def versionLink = ""
1541 def partialVersion = ""
1542 def firstPart = true
1543 rMap.version.split("\\.").each { part ->
1544 def displayPart = ( firstPart ? "" : "." ) + part
1545 partialVersion += displayPart
1547 linkedVersions.contains(partialVersion)
1548 || ( actualVersions.contains(partialVersion) && partialVersion != rMap.version )
1550 versionLink += displayPart
1552 versionLink += "<a id=\"Jalview.${partialVersion}\">${displayPart}</a>"
1553 linkedVersions += partialVersion
1557 def displayDate = releaseFilesDates[rFile].format("dd/MM/yyyy")
1560 def rContentProcessed = ""
1561 rContent.eachLine { line ->
1562 if (lm = line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
1563 line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}"
1564 } else if (lm = line =~ /^###([^#]+.*)$/) {
1565 line = "_${lm[0][1].trim()}_"
1567 rContentProcessed += line + "\n"
1570 def rContentSections = getMdSections(rContentProcessed)
1571 def rVersion = versionTemplate
1572 if (rVersion != "") {
1573 def rNewFeatures = rContentSections["new_features"]
1574 def rIssuesResolved = rContentSections["issues_resolved"]
1575 Node newFeaturesNode = parser.parse(rNewFeatures)
1576 String newFeaturesHtml = renderer.render(newFeaturesNode)
1577 Node issuesResolvedNode = parser.parse(rIssuesResolved)
1578 String issuesResolvedHtml = renderer.render(issuesResolvedNode)
1579 rVersion = hugoTemplateSubstitutions(rVersion,
1581 VERSION: rMap.version,
1582 VERSION_LINK: versionLink,
1583 DISPLAY_DATE: displayDate,
1584 NEW_FEATURES: newFeaturesHtml,
1585 ISSUES_RESOLVED: issuesResolvedHtml
1588 versionsHtml += rVersion
1592 releasesTemplate = releasesTemplate.replaceAll("(?s)__VERSION_LOOP_START__.*__VERSION_LOOP_END__", versionsHtml)
1593 releasesTemplate = hugoTemplateSubstitutions(releasesTemplate)
1594 releasesHtmlFile.text = releasesTemplate
1596 if (whatsnewMdFile.exists()) {
1597 def wnDisplayDate = releaseFilesDates[releaseMdFile] != null ? releaseFilesDates[releaseMdFile].format("dd MMMM yyyy") : ""
1598 def whatsnewMd = hugoTemplateSubstitutions(whatsnewMdFile.text)
1599 Node whatsnewNode = parser.parse(whatsnewMd)
1600 String whatsnewHtml = renderer.render(whatsnewNode)
1601 whatsnewHtml = whatsnewTemplateFile.text.replaceAll("__WHATS_NEW__", whatsnewHtml)
1602 whatsnewHtmlFile.text = hugoTemplateSubstitutions(whatsnewHtml,
1604 VERSION: JALVIEW_VERSION,
1605 DISPLAY_DATE: wnDisplayDate
1608 } else if (gradle.taskGraph.hasTask(":linkCheck")) {
1609 whatsnewHtmlFile.text = "Development build " + getDate("yyyy-MM-dd HH:mm:ss")
1614 inputs.file(releasesTemplateFile)
1615 inputs.file(whatsnewTemplateFile)
1616 inputs.dir(releasesMdDir)
1617 inputs.dir(whatsnewMdDir)
1618 outputs.file(releasesHtmlFile)
1619 outputs.file(whatsnewHtmlFile)
1623 task copyResources(type: Copy) {
1625 description = "Copy (and make text substitutions in) the resources dir to the build area"
1627 def inputDir = resourceDir
1628 def outputDir = resourcesBuildDir
1632 include('**/*.html')
1634 filter(ReplaceTokens,
1638 'Version-Rel': JALVIEW_VERSION,
1639 'Year-Rel': getDate("yyyy")
1646 exclude('**/*.html')
1651 inputs.dir(inputDir)
1652 outputs.dir(outputDir)
1655 task copyChannelResources(type: Copy) {
1656 dependsOn copyResources
1658 description = "Copy the channel resources dir to the build resources area"
1660 def inputDir = "${channelDir}/${resource_dir}"
1661 def outputDir = resourcesBuildDir
1663 include(channel_props)
1664 filter(ReplaceTokens,
1668 'SUFFIX': channelSuffix
1673 exclude(channel_props)
1677 inputs.dir(inputDir)
1678 outputs.dir(outputDir)
1681 task createBuildProperties(type: WriteProperties) {
1682 dependsOn copyResources
1684 description = "Create the ${buildProperties} file"
1686 inputs.dir(sourceDir)
1687 inputs.dir(resourcesBuildDir)
1688 outputFile (buildProperties)
1689 // taking time specific comment out to allow better incremental builds
1690 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1691 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1692 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1693 property "VERSION", JALVIEW_VERSION
1694 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1695 property "JAVA_COMPILE_VERSION", JAVA_INTEGER_VERSION
1696 if (getdownSetAppBaseProperty) {
1697 property "GETDOWNAPPBASE", getdownAppBase
1698 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1700 outputs.file(outputFile)
1704 task buildIndices(type: JavaExec) {
1706 classpath = sourceSets.main.compileClasspath
1707 main = "com.sun.java.help.search.Indexer"
1708 workingDir = "${helpBuildDir}/${help_dir}"
1711 inputs.dir("${workingDir}/${argDir}")
1713 outputs.dir("${classesDir}/doc")
1714 outputs.dir("${classesDir}/help")
1715 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1716 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1717 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1718 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1719 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1720 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1723 task buildResources {
1724 dependsOn copyResources
1725 dependsOn copyChannelResources
1726 dependsOn createBuildProperties
1730 dependsOn buildResources
1733 dependsOn releasesTemplates
1734 dependsOn convertMdFiles
1735 dependsOn buildIndices
1739 compileJava.dependsOn prepare
1740 run.dependsOn compileJava
1741 //run.dependsOn prepare
1744 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1749 dependsOn cloverClasses
1751 dependsOn compileJava //?
1755 includeGroups testng_groups
1756 excludeGroups testng_excluded_groups
1758 useDefaultListeners=true
1761 maxHeapSize = "1024m"
1763 workingDir = jalviewDir
1764 def testLaf = project.findProperty("test_laf")
1765 if (testLaf != null) {
1766 println("Setting Test LaF to '${testLaf}'")
1767 systemProperty "laf", testLaf
1769 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1770 if (testHiDPIScale != null) {
1771 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1772 systemProperty "sun.java2d.uiScale", testHiDPIScale
1774 sourceCompatibility = compile_source_compatibility
1775 targetCompatibility = compile_target_compatibility
1776 jvmArgs += additional_compiler_args
1780 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1786 task compileLinkCheck(type: JavaCompile) {
1788 classpath = files("${jalviewDir}/${utils_dir}")
1789 destinationDir = file("${jalviewDir}/${utils_dir}")
1790 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1792 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1793 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1794 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1795 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1799 task linkCheck(type: JavaExec) {
1801 dependsOn compileLinkCheck
1803 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1804 classpath = files("${jalviewDir}/${utils_dir}")
1805 main = "HelpLinksChecker"
1806 workingDir = "${helpBuildDir}"
1807 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1809 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1810 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1813 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1817 inputs.dir(helpBuildDir)
1818 outputs.file(helpLinksCheckerOutFile)
1822 // import the pubhtmlhelp target
1823 ant.properties.basedir = "${jalviewDir}"
1824 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1825 ant.importBuild "${utils_dir}/publishHelp.xml"
1828 task cleanPackageDir(type: Delete) {
1830 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1840 attributes "Main-Class": main_class,
1841 "Permissions": "all-permissions",
1842 "Application-Name": applicationName,
1843 "Codebase": application_codebase,
1844 "Implementation-Version": JALVIEW_VERSION
1847 def outputDir = "${jalviewDir}/${package_dir}"
1848 destinationDirectory = file(outputDir)
1849 archiveFileName = rootProject.name+".jar"
1850 duplicatesStrategy "EXCLUDE"
1857 exclude "**/*.jar.*"
1859 inputs.dir(sourceSets.main.java.outputDir)
1860 sourceSets.main.resources.srcDirs.each{ dir ->
1863 outputs.file("${outputDir}/${archiveFileName}")
1867 task copyJars(type: Copy) {
1868 from fileTree(dir: classesDir, include: "**/*.jar").files
1869 into "${jalviewDir}/${package_dir}"
1873 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1874 task syncJars(type: Sync) {
1876 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1877 into "${jalviewDir}/${package_dir}"
1879 include jar.archiveFileName.getOrNull()
1886 description = "Put all required libraries in dist"
1887 // order of "cleanPackageDir", "copyJars", "jar" important!
1888 jar.mustRunAfter cleanPackageDir
1889 syncJars.mustRunAfter cleanPackageDir
1890 dependsOn cleanPackageDir
1893 outputs.dir("${jalviewDir}/${package_dir}")
1898 dependsOn cleanPackageDir
1905 group = "distribution"
1906 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1910 from ("${jalviewDir}/${libDistDir}") {
1914 attributes "Implementation-Version": JALVIEW_VERSION,
1915 "Application-Name": applicationName
1918 duplicatesStrategy "INCLUDE"
1920 mainClassName = shadow_jar_main_class
1922 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1926 task getdownImagesCopy() {
1927 inputs.dir getdownImagesDir
1928 outputs.dir getdownImagesBuildDir
1932 from(getdownImagesDir) {
1933 include("*getdown*.png")
1935 into getdownImagesBuildDir
1940 task getdownImagesProcess() {
1941 dependsOn getdownImagesCopy
1944 if (backgroundImageText) {
1945 if (convertBinary == null) {
1946 throw new StopExecutionException("No ImageMagick convert binary installed at '${convertBinaryExpectedLocation}'")
1948 if (!project.hasProperty("getdown_background_image_text_suffix_cmd")) {
1949 throw new StopExecutionException("No property 'getdown_background_image_text_suffix_cmd' defined. See channel_gradle.properties for channel ${CHANNEL}")
1951 fileTree(dir: getdownImagesBuildDir, include: "*background*.png").getFiles().each { file ->
1953 executable convertBinary
1956 '-font', getdown_background_image_text_font,
1957 '-fill', getdown_background_image_text_colour,
1958 '-draw', sprintf(getdown_background_image_text_suffix_cmd, channelSuffix),
1959 '-draw', sprintf(getdown_background_image_text_commit_cmd, "git-commit: ${gitHash}"),
1960 '-draw', sprintf(getdown_background_image_text_date_cmd, getDate("yyyy-MM-dd HH:mm:ss")),
1969 task getdownImages() {
1970 dependsOn getdownImagesProcess
1973 task getdownWebsite() {
1974 group = "distribution"
1975 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1977 dependsOn getdownImages
1982 def getdownWebsiteResourceFilenames = []
1983 def getdownResourceDir = getdownResourceDir
1984 def getdownResourceFilenames = []
1987 // clean the getdown website and files dir before creating getdown folders
1988 delete getdownAppBaseDir
1989 delete getdownFilesDir
1992 from buildProperties
1993 rename(file(buildProperties).getName(), getdown_build_properties)
1996 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1999 from channelPropsFile
2000 filter(ReplaceTokens,
2004 'SUFFIX': channelSuffix
2007 into getdownAppBaseDir
2009 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
2011 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
2012 def props = project.properties.sort { it.key }
2013 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
2014 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
2016 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
2017 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
2019 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
2020 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
2022 if (getdownImagesBuildDir != null && file(getdownImagesBuildDir).exists()) {
2023 props.put("getdown_txt_ui.background_image", "${getdownImagesBuildDir}/${getdown_background_image}")
2024 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesBuildDir}/${getdown_instant_background_image}")
2025 props.put("getdown_txt_ui.error_background", "${getdownImagesBuildDir}/${getdown_error_background}")
2026 props.put("getdown_txt_ui.progress_image", "${getdownImagesBuildDir}/${getdown_progress_image}")
2027 props.put("getdown_txt_ui.icon", "${getdownImagesBuildDir}/${getdown_icon}")
2028 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesBuildDir}/${getdown_mac_dock_icon}")
2031 props.put("getdown_txt_title", jalview_name)
2032 props.put("getdown_txt_ui.name", applicationName)
2034 // start with appbase
2035 getdownTextLines += "appbase = ${getdownAppBase}"
2036 props.each{ prop, val ->
2037 if (prop.startsWith("getdown_txt_") && val != null) {
2038 if (prop.startsWith("getdown_txt_multi_")) {
2039 def key = prop.substring(18)
2040 val.split(",").each{ v ->
2041 def line = "${key} = ${v}"
2042 getdownTextLines += line
2045 // file values rationalised
2046 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
2048 if (val.indexOf('/') == 0) {
2051 } else if (val.indexOf('/') > 0) {
2052 // relative path (relative to jalviewDir)
2053 r = file( "${jalviewDir}/${val}" )
2056 val = "${getdown_resource_dir}/" + r.getName()
2057 getdownWebsiteResourceFilenames += val
2058 getdownResourceFilenames += r.getPath()
2061 if (! prop.startsWith("getdown_txt_resource")) {
2062 def line = prop.substring(12) + " = ${val}"
2063 getdownTextLines += line
2069 getdownWebsiteResourceFilenames.each{ filename ->
2070 getdownTextLines += "resource = ${filename}"
2072 getdownResourceFilenames.each{ filename ->
2075 into getdownResourceDir
2079 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
2080 getdownWrapperScripts.each{ script ->
2081 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
2085 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
2087 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
2092 fileTree(file(package_dir)).each{ f ->
2093 if (f.isDirectory()) {
2094 def files = fileTree(dir: f, include: ["*"]).getFiles()
2096 } else if (f.exists()) {
2100 def jalviewJar = jar.archiveFileName.getOrNull()
2101 // put jalview.jar first for CLASSPATH and .properties files reasons
2102 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
2103 def name = f.getName()
2104 def line = "code = ${getdownAppDistDir}/${name}"
2105 getdownTextLines += line
2112 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
2114 if (JAVA_VERSION.equals("11")) {
2115 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
2116 j11libFiles.sort().each{f ->
2117 def name = f.getName()
2118 def line = "code = ${getdown_j11lib_dir}/${name}"
2119 getdownTextLines += line
2122 into getdownJ11libDir
2128 // 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.
2129 //getdownTextLines += "class = " + file(getdownLauncher).getName()
2130 getdownTextLines += "resource = ${getdown_launcher_new}"
2131 getdownTextLines += "class = ${main_class}"
2132 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
2133 if (getdownSetAppBaseProperty) {
2134 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
2135 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
2138 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
2139 getdownTxt.write(getdownTextLines.join("\n"))
2141 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
2142 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
2143 launchJvl.write("appbase=${getdownAppBase}")
2145 // files going into the getdown website dir: getdown-launcher.jar
2147 from getdownLauncher
2148 rename(file(getdownLauncher).getName(), getdown_launcher_new)
2149 into getdownAppBaseDir
2152 // files going into the getdown website dir: getdown-launcher(-local).jar
2154 from getdownLauncher
2155 if (file(getdownLauncher).getName() != getdown_launcher) {
2156 rename(file(getdownLauncher).getName(), getdown_launcher)
2158 into getdownAppBaseDir
2161 // files going into the getdown website dir: ./install dir and files
2162 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
2165 from getdownLauncher
2166 from "${getdownAppDir}/${getdown_build_properties}"
2167 if (file(getdownLauncher).getName() != getdown_launcher) {
2168 rename(file(getdownLauncher).getName(), getdown_launcher)
2170 into getdownInstallDir
2173 // and make a copy in the getdown files dir (these are not downloaded by getdown)
2175 from getdownInstallDir
2176 into getdownFilesInstallDir
2180 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2184 from getdownLauncher
2185 from "${getdownAppBaseDir}/${getdown_build_properties}"
2186 from "${getdownAppBaseDir}/${channel_props}"
2187 if (file(getdownLauncher).getName() != getdown_launcher) {
2188 rename(file(getdownLauncher).getName(), getdown_launcher)
2190 into getdownFilesDir
2193 // and ./resource (not all downloaded by getdown)
2195 from getdownResourceDir
2196 into "${getdownFilesDir}/${getdown_resource_dir}"
2201 inputs.dir("${jalviewDir}/${package_dir}")
2203 outputs.dir(getdownAppBaseDir)
2204 outputs.dir(getdownFilesDir)
2208 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
2209 task getdownDigestDir(type: JavaExec) {
2211 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
2213 def digestDirPropertyName = "DIGESTDIR"
2215 classpath = files(getdownLauncher)
2216 def digestDir = findProperty(digestDirPropertyName)
2217 if (digestDir == null) {
2218 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
2222 main = "com.threerings.getdown.tools.Digester"
2226 task getdownDigest(type: JavaExec) {
2227 group = "distribution"
2228 description = "Digest the getdown website folder"
2229 dependsOn getdownWebsite
2231 classpath = files(getdownLauncher)
2233 main = "com.threerings.getdown.tools.Digester"
2234 args getdownAppBaseDir
2235 inputs.dir(getdownAppBaseDir)
2236 outputs.file("${getdownAppBaseDir}/digest2.txt")
2241 group = "distribution"
2242 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
2243 dependsOn getdownDigest
2245 if (reportRsyncCommand) {
2246 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
2247 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
2248 println "LIKELY RSYNC COMMAND:"
2249 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
2250 if (RUNRSYNC == "true") {
2252 commandLine "mkdir", "-p", toDir
2255 commandLine "rsync", "-avh", "--delete", fromDir, toDir
2263 task getdownArchiveBuild() {
2264 group = "distribution"
2265 description = "Put files in the archive dir to go on the website"
2267 dependsOn getdownWebsite
2269 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
2270 def vDir = "${getdownArchiveDir}/${v}"
2271 getdownFullArchiveDir = "${vDir}/getdown"
2272 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
2274 def vAltDir = "alt_${v}"
2275 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
2278 // cleanup old "old" dir
2279 delete getdownArchiveDir
2281 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
2282 getdownArchiveTxt.getParentFile().mkdirs()
2283 def getdownArchiveTextLines = []
2284 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
2288 from "${getdownAppBaseDir}/${getdownAppDistDir}"
2289 into "${getdownFullArchiveDir}/${vAltDir}"
2292 getdownTextLines.each { line ->
2293 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
2294 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
2295 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
2296 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
2297 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
2298 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
2299 // remove the existing resource = resource/ or bin/ lines
2300 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
2301 getdownArchiveTextLines += line
2305 // the resource dir -- add these files as resource lines in getdown.txt
2307 from "${archiveImagesDir}"
2308 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
2310 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
2314 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
2316 def vLaunchJvl = file(getdownVersionLaunchJvl)
2317 vLaunchJvl.getParentFile().mkdirs()
2318 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
2319 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
2320 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
2321 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
2322 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
2323 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
2325 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2327 from getdownLauncher
2328 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
2329 from "${getdownAppBaseDir}/${getdown_launcher_new}"
2330 from "${getdownAppBaseDir}/${channel_props}"
2331 if (file(getdownLauncher).getName() != getdown_launcher) {
2332 rename(file(getdownLauncher).getName(), getdown_launcher)
2334 into getdownFullArchiveDir
2340 task getdownArchiveDigest(type: JavaExec) {
2341 group = "distribution"
2342 description = "Digest the getdown archive folder"
2344 dependsOn getdownArchiveBuild
2347 classpath = files(getdownLauncher)
2348 args getdownFullArchiveDir
2350 main = "com.threerings.getdown.tools.Digester"
2351 inputs.dir(getdownFullArchiveDir)
2352 outputs.file("${getdownFullArchiveDir}/digest2.txt")
2355 task getdownArchive() {
2356 group = "distribution"
2357 description = "Build the website archive dir with getdown digest"
2359 dependsOn getdownArchiveBuild
2360 dependsOn getdownArchiveDigest
2363 tasks.withType(JavaCompile) {
2364 options.encoding = 'UTF-8'
2370 delete getdownAppBaseDir
2371 delete getdownFilesDir
2372 delete getdownArchiveDir
2378 if (file(install4jHomeDir).exists()) {
2380 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
2381 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
2382 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
2383 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
2385 installDir(file(install4jHomeDir))
2387 mediaTypes = Arrays.asList(install4j_media_types.split(","))
2391 task copyInstall4jTemplate {
2392 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
2393 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
2394 inputs.file(install4jTemplateFile)
2395 inputs.file(install4jFileAssociationsFile)
2396 inputs.property("CHANNEL", { CHANNEL })
2397 outputs.file(install4jConfFile)
2400 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
2402 // turn off code signing if no OSX_KEYPASS
2403 if (OSX_KEYPASS == "") {
2404 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
2405 codeSigning.'@macEnabled' = "false"
2407 install4jConfigXml.'**'.windows.each { windows ->
2408 windows.'@runPostProcessor' = "false"
2412 // disable install screen for OSX dmg (for 2.11.2.0)
2413 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
2414 macosArchive.attributes().remove('executeSetupApp')
2415 macosArchive.attributes().remove('setupAppId')
2418 // turn off checksum creation for LOCAL channel
2419 def e = install4jConfigXml.application[0]
2420 e.'@createChecksums' = string(install4jCheckSums)
2422 // put file association actions where placeholder action is
2423 def install4jFileAssociationsText = install4jFileAssociationsFile.text
2424 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
2425 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
2426 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
2427 def parent = a.parent()
2429 fileAssociationActions.each { faa ->
2432 // don't need to continue in .any loop once replacements have been made
2437 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
2438 // NB we're deleting the /other/ one!
2439 // Also remove the examples subdir from non-release versions
2440 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
2441 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
2442 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
2443 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
2445 // remove the examples subdir from Full File Set
2446 def files = install4jConfigXml.files[0]
2447 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
2448 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
2449 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
2450 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
2451 dirEntry.parent().remove(dirEntry)
2453 install4jConfigXml.'**'.action.any { a ->
2454 if (a.'@customizedId' == customizedIdToDelete) {
2455 def parent = a.parent()
2461 // write install4j file
2462 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2469 delete install4jConfFile
2473 task cleanInstallersDataFiles {
2474 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2475 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2476 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2478 delete installersOutputTxt
2479 delete installersSha256
2480 delete hugoDataJsonFile
2484 task install4jDMGBackgroundImageCopy {
2485 inputs.file "${install4jDMGBackgroundImageDir}/${install4jDMGBackgroundImageFile}"
2486 outputs.dir "${install4jDMGBackgroundImageBuildDir}"
2489 from(install4jDMGBackgroundImageDir) {
2490 include(install4jDMGBackgroundImageFile)
2492 into install4jDMGBackgroundImageBuildDir
2497 task install4jDMGBackgroundImageProcess {
2498 dependsOn install4jDMGBackgroundImageCopy
2501 if (backgroundImageText) {
2502 if (convertBinary == null) {
2503 throw new StopExecutionException("No ImageMagick convert binary installed at '${convertBinaryExpectedLocation}'")
2505 if (!project.hasProperty("install4j_background_image_text_suffix_cmd")) {
2506 throw new StopExecutionException("No property 'install4j_background_image_text_suffix_cmd' defined. See channel_gradle.properties for channel ${CHANNEL}")
2508 fileTree(dir: install4jDMGBackgroundImageBuildDir, include: "*.png").getFiles().each { file ->
2510 executable convertBinary
2513 '-font', install4j_background_image_text_font,
2514 '-fill', install4j_background_image_text_colour,
2515 '-draw', sprintf(install4j_background_image_text_suffix_cmd, channelSuffix),
2516 '-draw', sprintf(install4j_background_image_text_commit_cmd, "git-commit: ${gitHash}"),
2517 '-draw', sprintf(install4j_background_image_text_date_cmd, getDate("yyyy-MM-dd HH:mm:ss")),
2526 task install4jDMGBackgroundImage {
2527 dependsOn install4jDMGBackgroundImageProcess
2530 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2531 group = "distribution"
2532 description = "Create the install4j installers"
2534 dependsOn copyInstall4jTemplate
2535 dependsOn cleanInstallersDataFiles
2536 dependsOn install4jDMGBackgroundImage
2538 projectFile = install4jConfFile
2540 // create an md5 for the input files to use as version for install4j conf file
2541 def digest = MessageDigest.getInstance("MD5")
2543 (file("${install4jDir}/${install4j_template}").text +
2544 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2545 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2546 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2547 if (filesMd5.length() >= 8) {
2548 filesMd5 = filesMd5.substring(0,8)
2550 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2553 'JALVIEW_NAME': jalview_name,
2554 'JALVIEW_APPLICATION_NAME': applicationName,
2555 'JALVIEW_DIR': "../..",
2556 'OSX_KEYSTORE': OSX_KEYSTORE,
2557 'OSX_APPLEID': OSX_APPLEID,
2558 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2559 'JSIGN_SH': JSIGN_SH,
2560 'JRE_DIR': getdown_app_dir_java,
2561 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2562 'JALVIEW_VERSION': JALVIEW_VERSION,
2563 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2564 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2565 'JAVA_VERSION': JAVA_VERSION,
2566 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2567 'VERSION': JALVIEW_VERSION,
2568 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2569 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2570 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2571 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2572 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2573 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2574 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2575 'BUNDLE_ID': install4jBundleId,
2576 'INTERNAL_ID': install4jInternalId,
2577 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2578 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2579 'MACOS_DMG_BG_IMAGE': "${install4jDMGBackgroundImageBuildDir}/${install4jDMGBackgroundImageFile}",
2580 'WRAPPER_LINK': getdownWrapperLink,
2581 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2582 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2583 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2584 'INSTALLER_NAME': install4jInstallerName,
2585 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2586 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2587 'GETDOWN_FILES_DIR': getdown_files_dir,
2588 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2589 'GETDOWN_DIST_DIR': getdownAppDistDir,
2590 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2591 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2592 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2593 'BUILD_DIR': install4jBuildDir,
2594 'APPLICATION_CATEGORIES': install4j_application_categories,
2595 'APPLICATION_FOLDER': install4jApplicationFolder,
2596 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2597 'EXECUTABLE_NAME': install4jExecutableName,
2598 'EXTRA_SCHEME': install4jExtraScheme,
2599 'MAC_ICONS_FILE': install4jMacIconsFile,
2600 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2601 'PNG_ICON_FILE': install4jPngIconFile,
2602 'BACKGROUND': install4jBackground,
2606 //println("INSTALL4J VARIABLES:")
2607 //variables.each{k,v->println("${k}=${v}")}
2609 destination = "${jalviewDir}/${install4jBuildDir}"
2610 buildSelected = true
2612 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2614 disableSigning = true
2615 disableNotarization = true
2619 macKeystorePassword = OSX_KEYPASS
2622 if (OSX_ALTOOLPASS) {
2623 appleIdPassword = OSX_ALTOOLPASS
2624 disableNotarization = false
2626 disableNotarization = true
2630 println("Using projectFile "+projectFile)
2631 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2635 inputs.dir(getdownAppBaseDir)
2636 inputs.file(install4jConfFile)
2637 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2638 inputs.dir(macosJavaVMDir)
2639 inputs.dir(windowsJavaVMDir)
2640 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2643 def getDataHash(File myFile) {
2644 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2645 return myFile.exists()
2647 "file" : myFile.getName(),
2648 "filesize" : myFile.length(),
2649 "sha256" : hash.toString()
2654 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2656 "channel" : getdownChannelName,
2657 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2658 "git-commit" : "${gitHash} [${gitBranch}]",
2659 "version" : JALVIEW_VERSION
2661 // install4j installer files
2662 if (installersOutputTxt.exists()) {
2664 installersOutputTxt.readLines().each { def line ->
2665 if (line.startsWith("#")) {
2668 line.replaceAll("\n","")
2669 def vals = line.split("\t")
2670 def filename = vals[3]
2671 def filesize = file(filename).length()
2672 filename = filename.replaceAll(/^.*\//, "")
2673 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2674 idHash."${filename}" = vals[0]
2676 if (install4jCheckSums && installersSha256.exists()) {
2677 installersSha256.readLines().each { def line ->
2678 if (line.startsWith("#")) {
2681 line.replaceAll("\n","")
2682 def vals = line.split(/\s+\*?/)
2683 def filename = vals[1]
2684 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2690 "JAR": shadowJar.archiveFile, // executable JAR
2691 "JVL": getdownVersionLaunchJvl, // version JVL
2692 "SOURCE": sourceDist.archiveFile // source TGZ
2693 ].each { key, value ->
2694 def file = file(value)
2695 if (file.exists()) {
2696 def fileHash = getDataHash(file)
2697 if (fileHash != null) {
2698 hash."${key}" = fileHash;
2702 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2705 task staticMakeInstallersJsonFile {
2707 def output = findProperty("i4j_output")
2708 def sha256 = findProperty("i4j_sha256")
2709 def json = findProperty("i4j_json")
2710 if (output == null || sha256 == null || json == null) {
2711 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2713 writeDataJsonFile(file(output), file(sha256), file(json))
2718 dependsOn installerFiles
2724 eclipse().configFile(eclipse_codestyle_file)
2728 task createSourceReleaseProperties(type: WriteProperties) {
2729 group = "distribution"
2730 description = "Create the source RELEASE properties file"
2732 def sourceTarBuildDir = "${buildDir}/sourceTar"
2733 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2734 outputFile (sourceReleasePropertiesFile)
2737 releaseProps.each{ key, val -> property key, val }
2738 property "git.branch", gitBranch
2739 property "git.hash", gitHash
2742 outputs.file(outputFile)
2745 task sourceDist(type: Tar) {
2746 group "distribution"
2747 description "Create a source .tar.gz file for distribution"
2749 dependsOn createBuildProperties
2750 dependsOn convertMdFiles
2751 dependsOn eclipseAllPreferences
2752 dependsOn createSourceReleaseProperties
2755 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2756 archiveFileName = outputFileName
2758 compression Compression.GZIP
2773 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2775 "utils/InstallAnywhere",
2790 "gradle.properties",
2802 ".settings/org.eclipse.buildship.core.prefs",
2803 ".settings/org.eclipse.jdt.core.prefs"
2807 exclude (EXCLUDE_FILES)
2808 include (PROCESS_FILES)
2809 filter(ReplaceTokens,
2813 'Version-Rel': JALVIEW_VERSION,
2814 'Year-Rel': getDate("yyyy")
2819 exclude (EXCLUDE_FILES)
2820 exclude (PROCESS_FILES)
2821 exclude ("appletlib")
2822 exclude ("**/*locales")
2823 exclude ("*locales/**")
2824 exclude ("utils/InstallAnywhere")
2826 exclude (getdown_files_dir)
2827 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2828 //exclude (getdown_website_dir)
2829 //exclude (getdown_archive_dir)
2831 // exluding these as not using jars as modules yet
2832 exclude ("${j11modDir}/**/*.jar")
2835 include(INCLUDE_FILES)
2837 // from (jalviewDir) {
2838 // // explicit includes for stuff that seemed to not get included
2839 // include(fileTree("test/**/*."))
2840 // exclude(EXCLUDE_FILES)
2841 // exclude(PROCESS_FILES)
2844 from(file(buildProperties).getParent()) {
2845 include(file(buildProperties).getName())
2846 rename(file(buildProperties).getName(), "build_properties")
2848 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2852 def sourceTarBuildDir = "${buildDir}/sourceTar"
2853 from(sourceTarBuildDir) {
2854 // this includes the appended RELEASE properties file
2858 task dataInstallersJson {
2860 description "Create the installers-VERSION.json data file for installer files created"
2862 mustRunAfter installers
2863 mustRunAfter shadowJar
2864 mustRunAfter sourceDist
2865 mustRunAfter getdownArchive
2867 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2868 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2870 if (installersOutputTxt.exists()) {
2871 inputs.file(installersOutputTxt)
2873 if (install4jCheckSums && installersSha256.exists()) {
2874 inputs.file(installersSha256)
2877 shadowJar.archiveFile, // executable JAR
2878 getdownVersionLaunchJvl, // version JVL
2879 sourceDist.archiveFile // source TGZ
2880 ].each { fileName ->
2881 if (file(fileName).exists()) {
2882 inputs.file(fileName)
2886 outputs.file(hugoDataJsonFile)
2889 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2895 description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'."
2898 dependsOn pubhtmlhelp
2900 inputs.dir("${helpBuildDir}/${help_dir}")
2901 outputs.dir("${buildDir}/distributions/${help_dir}")
2905 task j2sSetHeadlessBuild {
2912 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2914 description "Enable the alternative J2S Config file for headless build"
2916 outputFile = jalviewjsJ2sSettingsFileName
2917 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2918 def j2sProps = new Properties()
2919 if (j2sPropsFile.exists()) {
2921 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2922 j2sProps.load(j2sPropsFileFIS)
2923 j2sPropsFileFIS.close()
2925 j2sProps.each { prop, val ->
2928 } catch (Exception e) {
2929 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2933 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2934 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2939 task jalviewjsSetEclipseWorkspace {
2940 def propKey = "jalviewjs_eclipse_workspace"
2942 if (project.hasProperty(propKey)) {
2943 propVal = project.getProperty(propKey)
2944 if (propVal.startsWith("~/")) {
2945 propVal = System.getProperty("user.home") + propVal.substring(1)
2948 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2949 def propsFile = file(propsFileName)
2950 def eclipseWsDir = propVal
2951 def props = new Properties()
2953 def writeProps = true
2954 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2955 def ins = new FileInputStream(propsFileName)
2958 if (props.getProperty(propKey, null) != null) {
2959 eclipseWsDir = props.getProperty(propKey)
2964 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2965 def tempDir = File.createTempDir()
2966 eclipseWsDir = tempDir.getAbsolutePath()
2969 eclipseWorkspace = file(eclipseWsDir)
2972 // do not run a headless transpile when we claim to be in Eclipse
2974 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2975 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2977 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2981 props.setProperty(propKey, eclipseWsDir)
2982 propsFile.parentFile.mkdirs()
2983 def bytes = new ByteArrayOutputStream()
2984 props.store(bytes, null)
2985 def propertiesString = bytes.toString()
2986 propsFile.text = propertiesString
2992 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2995 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2996 outputs.file(propsFileName)
2997 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
3001 task jalviewjsEclipsePaths {
3004 def eclipseRoot = jalviewjs_eclipse_root
3005 if (eclipseRoot.startsWith("~/")) {
3006 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
3008 if (OperatingSystem.current().isMacOsX()) {
3009 eclipseRoot += "/Eclipse.app"
3010 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
3011 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
3012 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
3013 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
3014 eclipseRoot += "/eclipse"
3016 eclipseBinary = "${eclipseRoot}/eclipse.exe"
3017 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
3018 } else { // linux or unix
3019 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
3020 eclipseRoot += "/eclipse"
3021 println("eclipseDir exists")
3023 eclipseBinary = "${eclipseRoot}/eclipse"
3024 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
3027 eclipseVersion = "4.13" // default
3028 def assumedVersion = true
3029 if (file(eclipseProduct).exists()) {
3030 def fis = new FileInputStream(eclipseProduct)
3031 def props = new Properties()
3033 eclipseVersion = props.getProperty("version")
3035 assumedVersion = false
3038 def propKey = "eclipse_debug"
3039 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
3042 // do not run a headless transpile when we claim to be in Eclipse
3044 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3045 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3047 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3050 if (!assumedVersion) {
3051 println("ECLIPSE VERSION=${eclipseVersion}")
3057 task printProperties {
3059 description "Output to console all System.properties"
3061 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
3067 dependsOn eclipseProject
3068 dependsOn eclipseClasspath
3069 dependsOn eclipseJdt
3073 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
3074 task jalviewjsEclipseCopyDropins(type: Copy) {
3075 dependsOn jalviewjsEclipsePaths
3077 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
3078 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
3079 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
3086 // this eclipse -clean doesn't actually work
3087 task jalviewjsCleanEclipse(type: Exec) {
3088 dependsOn eclipseSetup
3089 dependsOn jalviewjsEclipsePaths
3090 dependsOn jalviewjsEclipseCopyDropins
3092 executable(eclipseBinary)
3093 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
3099 def inputString = """exit
3102 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
3103 standardInput = inputByteStream
3106 /* not really working yet
3107 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
3111 task jalviewjsTransferUnzipSwingJs {
3112 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
3116 from zipTree(file_zip)
3117 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3121 inputs.file file_zip
3122 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3126 task jalviewjsTransferUnzipLib {
3127 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
3130 zipFiles.each { file_zip ->
3132 from zipTree(file_zip)
3133 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3138 inputs.files zipFiles
3139 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3143 task jalviewjsTransferUnzipAllLibs {
3144 dependsOn jalviewjsTransferUnzipSwingJs
3145 dependsOn jalviewjsTransferUnzipLib
3149 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
3151 description "Create the alternative j2s file from the j2s.* properties"
3153 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
3154 def siteDirProperty = "j2s.site.directory"
3155 def setSiteDir = false
3156 jalviewjsJ2sProps.each { prop, val ->
3158 if (prop == siteDirProperty) {
3159 if (!(val.startsWith('/') || val.startsWith("file://") )) {
3160 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3166 if (!setSiteDir) { // default site location, don't override specifically set property
3167 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3170 outputFile = jalviewjsJ2sAltSettingsFileName
3173 inputs.properties(jalviewjsJ2sProps)
3174 outputs.file(jalviewjsJ2sAltSettingsFileName)
3179 task jalviewjsEclipseSetup {
3180 dependsOn jalviewjsEclipseCopyDropins
3181 dependsOn jalviewjsSetEclipseWorkspace
3182 dependsOn jalviewjsCreateJ2sSettings
3186 task jalviewjsSyncAllLibs (type: Sync) {
3187 dependsOn jalviewjsTransferUnzipAllLibs
3188 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3189 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3190 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3194 def outputFiles = []
3195 rename { filename ->
3196 outputFiles += "${outputDir}/${filename}"
3203 // should this be exclude really ?
3204 duplicatesStrategy "INCLUDE"
3206 outputs.files outputFiles
3207 inputs.files inputFiles
3211 task jalviewjsSyncResources (type: Sync) {
3212 dependsOn buildResources
3214 def inputFiles = fileTree(dir: resourcesBuildDir)
3215 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3219 def outputFiles = []
3220 rename { filename ->
3221 outputFiles += "${outputDir}/${filename}"
3227 outputs.files outputFiles
3228 inputs.files inputFiles
3232 task jalviewjsSyncSiteResources (type: Sync) {
3233 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3234 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3238 def outputFiles = []
3239 rename { filename ->
3240 outputFiles += "${outputDir}/${filename}"
3246 outputs.files outputFiles
3247 inputs.files inputFiles
3251 task jalviewjsSyncBuildProperties (type: Sync) {
3252 dependsOn createBuildProperties
3253 def inputFiles = [file(buildProperties)]
3254 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3258 def outputFiles = []
3259 rename { filename ->
3260 outputFiles += "${outputDir}/${filename}"
3266 outputs.files outputFiles
3267 inputs.files inputFiles
3271 task jalviewjsProjectImport(type: Exec) {
3272 dependsOn eclipseSetup
3273 dependsOn jalviewjsEclipsePaths
3274 dependsOn jalviewjsEclipseSetup
3277 // do not run a headless import when we claim to be in Eclipse
3279 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3280 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3282 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3286 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3287 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3288 executable(eclipseBinary)
3289 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3293 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3295 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3296 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3299 inputs.file("${jalviewDir}/.project")
3300 outputs.upToDateWhen {
3301 file(projdir).exists()
3306 task jalviewjsTranspile(type: Exec) {
3307 dependsOn jalviewjsEclipseSetup
3308 dependsOn jalviewjsProjectImport
3309 dependsOn jalviewjsEclipsePaths
3311 dependsOn jalviewjsEnableAltFileProperty
3315 // do not run a headless transpile when we claim to be in Eclipse
3317 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3318 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3320 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3324 executable(eclipseBinary)
3325 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3329 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3331 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3332 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3338 stdout = new ByteArrayOutputStream()
3339 stderr = new ByteArrayOutputStream()
3341 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3342 def logOutFile = file(logOutFileName)
3343 logOutFile.createNewFile()
3344 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3345 BINARY: ${eclipseBinary}
3346 VERSION: ${eclipseVersion}
3347 WORKSPACE: ${eclipseWorkspace}
3348 DEBUG: ${eclipseDebug}
3351 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3352 // combine stdout and stderr
3353 def logErrFOS = logOutFOS
3355 if (jalviewjs_j2s_to_console.equals("true")) {
3356 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3357 new org.apache.tools.ant.util.TeeOutputStream(
3361 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3362 new org.apache.tools.ant.util.TeeOutputStream(
3367 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3370 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3377 if (stdout.toString().contains("Error processing ")) {
3378 // j2s did not complete transpile
3379 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3380 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3381 println("IGNORING TRANSPILE ERRORS")
3382 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3384 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3389 inputs.dir("${jalviewDir}/${sourceDir}")
3390 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3391 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3395 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3397 def stdout = new ByteArrayOutputStream()
3398 def stderr = new ByteArrayOutputStream()
3400 def coreFile = file(jsfile)
3402 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3404 logOutFile.createNewFile()
3405 logOutFile.append(msg+"\n")
3407 def coreTop = file(prefixFile)
3408 def coreBottom = file(suffixFile)
3409 coreFile.getParentFile().mkdirs()
3410 coreFile.createNewFile()
3411 coreFile.write( coreTop.getText("UTF-8") )
3415 def t = f.getText("UTF-8")
3416 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3417 coreFile.append( t )
3419 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3421 logOutFile.append(msg+"\n")
3424 coreFile.append( coreBottom.getText("UTF-8") )
3426 msg = "Generating ${zjsfile}"
3428 logOutFile.append(msg+"\n")
3429 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3430 def logErrFOS = logOutFOS
3433 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3434 main = "com.google.javascript.jscomp.CommandLineRunner"
3435 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3436 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3439 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3441 logOutFile.append(msg+"\n")
3443 if (logOutConsole) {
3444 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3445 new org.apache.tools.ant.util.TeeOutputStream(
3449 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3450 new org.apache.tools.ant.util.TeeOutputStream(
3455 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3458 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3465 logOutFile.append(msg+"\n")
3469 task jalviewjsBuildAllCores {
3471 description "Build the core js lib closures listed in the classlists dir"
3472 dependsOn jalviewjsTranspile
3473 dependsOn jalviewjsTransferUnzipSwingJs
3475 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3476 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3477 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3478 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3479 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3480 def prefixFile = "${jsDir}/core/coretop2.js"
3481 def suffixFile = "${jsDir}/core/corebottom2.js"
3483 inputs.file prefixFile
3484 inputs.file suffixFile
3486 def classlistFiles = []
3487 // add the classlists found int the jalviewjs_classlists_dir
3488 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3490 def name = file.getName() - ".txt"
3497 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3498 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3499 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3501 jalviewjsCoreClasslists = []
3503 classlistFiles.each {
3506 def file = hash['file']
3507 if (! file.exists()) {
3508 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3509 return false // this is a "continue" in groovy .each closure
3511 def name = hash['name']
3513 name = file.getName() - ".txt"
3521 def list = fileTree(dir: j2sDir, includes: filelist)
3523 def jsfile = "${outputDir}/core${name}.js"
3524 def zjsfile = "${outputDir}/core${name}.z.js"
3526 jalviewjsCoreClasslists += [
3535 outputs.file(jsfile)
3536 outputs.file(zjsfile)
3539 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3540 def stevesoftClasslistName = "_stevesoft"
3541 def stevesoftClasslist = [
3542 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3543 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3544 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3545 'name': stevesoftClasslistName
3547 jalviewjsCoreClasslists += stevesoftClasslist
3548 inputs.files(stevesoftClasslist['list'])
3549 outputs.file(stevesoftClasslist['jsfile'])
3550 outputs.file(stevesoftClasslist['zjsfile'])
3553 def allClasslistName = "_all"
3554 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3555 allJsFiles += fileTree(
3559 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3560 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3561 "**/org/jmol/export/JSExporter.js"
3564 allJsFiles += fileTree(
3568 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3569 "**/sun/misc/Unsafe.js",
3570 "**/swingjs/jquery/jquery-editable-select.js",
3571 "**/swingjs/jquery/j2sComboBox.js",
3572 "**/sun/misc/FloatingDecimal.js"
3575 def allClasslist = [
3576 'jsfile': "${outputDir}/core${allClasslistName}.js",
3577 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3579 'name': allClasslistName
3581 // not including this version of "all" core at the moment
3582 //jalviewjsCoreClasslists += allClasslist
3583 inputs.files(allClasslist['list'])
3584 outputs.file(allClasslist['jsfile'])
3585 outputs.file(allClasslist['zjsfile'])
3588 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3589 logOutFile.getParentFile().mkdirs()
3590 logOutFile.createNewFile()
3591 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3593 jalviewjsCoreClasslists.each {
3594 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3601 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3604 into file(outputFile).getParentFile()
3605 rename { filename ->
3606 if (filename.equals(inputFile.getName())) {
3607 return file(outputFile).getName()
3611 filter(ReplaceTokens,
3615 'MAIN': '"'+main_class+'"',
3617 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3618 'COREKEY': jalviewjs_core_key,
3619 'CORENAME': coreName
3626 task jalviewjsPublishCoreTemplates {
3627 dependsOn jalviewjsBuildAllCores
3628 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3629 def inputFile = file(inputFileName)
3630 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3632 def outputFiles = []
3633 jalviewjsCoreClasslists.each { cl ->
3634 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3635 cl['outputfile'] = outputFile
3636 outputFiles += outputFile
3640 jalviewjsCoreClasslists.each { cl ->
3641 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3644 inputs.file(inputFile)
3645 outputs.files(outputFiles)
3649 task jalviewjsSyncCore (type: Sync) {
3650 dependsOn jalviewjsBuildAllCores
3651 dependsOn jalviewjsPublishCoreTemplates
3652 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3653 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3657 def outputFiles = []
3658 rename { filename ->
3659 outputFiles += "${outputDir}/${filename}"
3665 outputs.files outputFiles
3666 inputs.files inputFiles
3670 // this Copy version of TransferSiteJs will delete anything else in the target dir
3671 task jalviewjsCopyTransferSiteJs(type: Copy) {
3672 dependsOn jalviewjsTranspile
3673 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3674 into "${jalviewDir}/${jalviewjsSiteDir}"
3678 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3679 task jalviewjsSyncTransferSiteJs(type: Sync) {
3680 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3682 into "${jalviewDir}/${jalviewjsSiteDir}"
3689 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3690 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3691 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3692 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3694 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3695 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3696 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3697 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3700 task jalviewjsPrepareSite {
3702 description "Prepares the website folder including unzipping files and copying resources"
3703 dependsOn jalviewjsSyncAllLibs
3704 dependsOn jalviewjsSyncResources
3705 dependsOn jalviewjsSyncSiteResources
3706 dependsOn jalviewjsSyncBuildProperties
3707 dependsOn jalviewjsSyncCore
3711 task jalviewjsBuildSite {
3713 description "Builds the whole website including transpiled code"
3714 dependsOn jalviewjsCopyTransferSiteJs
3715 dependsOn jalviewjsPrepareSite
3719 task cleanJalviewjsTransferSite {
3721 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3722 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3723 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3724 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3729 task cleanJalviewjsSite {
3730 dependsOn cleanJalviewjsTransferSite
3732 delete "${jalviewDir}/${jalviewjsSiteDir}"
3737 task jalviewjsSiteTar(type: Tar) {
3739 description "Creates a tar.gz file for the website"
3740 dependsOn jalviewjsBuildSite
3741 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3742 archiveFileName = outputFilename
3744 compression Compression.GZIP
3746 from "${jalviewDir}/${jalviewjsSiteDir}"
3747 into jalviewjs_site_dir // this is inside the tar file
3749 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3753 task jalviewjsServer {
3755 def filename = "jalviewjsTest.html"
3756 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3757 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3762 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3763 factory = f.newInstance()
3764 } catch (ClassNotFoundException e) {
3765 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3767 def port = Integer.valueOf(jalviewjs_server_port)
3772 while(port < start+1000 && !running) {
3774 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3775 jalviewjsServer = factory.start(doc_root, port)
3777 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3778 println("SERVER STARTED with document root ${doc_root}.")
3779 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3780 println("For debug: "+url+"?j2sdebug")
3781 println("For verbose: "+url+"?j2sverbose")
3782 } catch (Exception e) {
3787 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3788 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3789 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3791 jalviewjsCoreClasslists.each { cl ->
3792 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3794 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3796 println("For core ${cl.name}: "+urlcore)
3799 file(htmlFile).text = htmlText
3802 outputs.file(htmlFile)
3803 outputs.upToDateWhen({false})
3807 task cleanJalviewjsAll {
3809 description "Delete all configuration and build artifacts to do with JalviewJS build"
3810 dependsOn cleanJalviewjsSite
3811 dependsOn jalviewjsEclipsePaths
3814 delete "${jalviewDir}/${jalviewjsBuildDir}"
3815 delete "${jalviewDir}/${eclipse_bin_dir}"
3816 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3817 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3819 delete jalviewjsJ2sAltSettingsFileName
3822 outputs.upToDateWhen( { false } )
3826 task jalviewjsIDE_checkJ2sPlugin {
3827 group "00 JalviewJS in Eclipse"
3828 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3831 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3832 def j2sPluginFile = file(j2sPlugin)
3833 def eclipseHome = System.properties["eclipse.home.location"]
3834 if (eclipseHome == null || ! IN_ECLIPSE) {
3835 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3837 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3838 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3839 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3840 eclipseJ2sPluginDirs += altPluginsDir
3842 def foundPlugin = false
3843 def j2sPluginFileName = j2sPluginFile.getName()
3844 def eclipseJ2sPlugin
3845 def eclipseJ2sPluginFile
3846 eclipseJ2sPluginDirs.any { dir ->
3847 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3848 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3849 if (eclipseJ2sPluginFile.exists()) {
3855 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3856 System.err.println(msg)
3857 throw new StopExecutionException(msg)
3860 def digest = MessageDigest.getInstance("MD5")
3862 digest.update(j2sPluginFile.text.bytes)
3863 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3865 digest.update(eclipseJ2sPluginFile.text.bytes)
3866 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3868 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3869 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3870 System.err.println(msg)
3871 throw new StopExecutionException(msg)
3873 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3879 task jalviewjsIDE_copyJ2sPlugin {
3880 group "00 JalviewJS in Eclipse"
3881 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3884 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3885 def j2sPluginFile = file(j2sPlugin)
3886 def eclipseHome = System.properties["eclipse.home.location"]
3887 if (eclipseHome == null || ! IN_ECLIPSE) {
3888 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3890 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3891 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3892 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3893 System.err.println(msg)
3896 eclipseJ2sPluginFile.getParentFile().mkdirs()
3897 into eclipseJ2sPluginFile.getParent()
3903 task jalviewjsIDE_j2sFile {
3904 group "00 JalviewJS in Eclipse"
3905 description "Creates the .j2s file"
3906 dependsOn jalviewjsCreateJ2sSettings
3910 task jalviewjsIDE_SyncCore {
3911 group "00 JalviewJS in Eclipse"
3912 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3913 dependsOn jalviewjsSyncCore
3917 task jalviewjsIDE_SyncSiteAll {
3918 dependsOn jalviewjsSyncAllLibs
3919 dependsOn jalviewjsSyncResources
3920 dependsOn jalviewjsSyncSiteResources
3921 dependsOn jalviewjsSyncBuildProperties
3925 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3928 task jalviewjsIDE_PrepareSite {
3929 group "00 JalviewJS in Eclipse"
3930 description "Sync libs and resources to site dir, but not closure cores"
3932 dependsOn jalviewjsIDE_SyncSiteAll
3933 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3937 task jalviewjsIDE_AssembleSite {
3938 group "00 JalviewJS in Eclipse"
3939 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3940 dependsOn jalviewjsPrepareSite
3944 task jalviewjsIDE_SiteClean {
3945 group "00 JalviewJS in Eclipse"
3946 description "Deletes the Eclipse transpiled site"
3947 dependsOn cleanJalviewjsSite
3951 task jalviewjsIDE_Server {
3952 group "00 JalviewJS in Eclipse"
3953 description "Starts a webserver on localhost to test the website"
3954 dependsOn jalviewjsServer
3958 // buildship runs this at import or gradle refresh
3959 task eclipseSynchronizationTask {
3960 //dependsOn eclipseSetup
3961 dependsOn createBuildProperties
3963 dependsOn jalviewjsIDE_j2sFile
3964 dependsOn jalviewjsIDE_checkJ2sPlugin
3965 dependsOn jalviewjsIDE_PrepareSite
3970 // buildship runs this at build time or project refresh
3971 task eclipseAutoBuildTask {
3972 //dependsOn jalviewjsIDE_checkJ2sPlugin
3973 //dependsOn jalviewjsIDE_PrepareSite
3979 description "Build the site"
3980 dependsOn jalviewjsBuildSite