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 = false
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"
261 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
262 getdownAppDistDir = getdown_app_dir_release
263 getdownSetAppBaseProperty = true
264 reportRsyncCommand = true
266 install4jInstallerName = "${jalview_name} Installer"
270 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
271 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
272 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
273 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
274 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
276 package_dir = string("${ARCHIVEDIR}/${package_dir}")
277 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
280 reportRsyncCommand = true
281 install4jExtraScheme = "jalviewa"
285 getdownChannelName = string("archive/${JALVIEW_VERSION}")
286 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
287 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
288 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
289 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
291 package_dir = string("${ARCHIVEDIR}/${package_dir}")
292 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
295 reportRsyncCommand = true
296 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
297 install4jSuffix = "Archive"
298 install4jExtraScheme = "jalviewa"
301 case ~/^DEVELOP-([\.\-\w]*)$/:
302 def suffix = Matcher.lastMatcher[0][1]
303 reportRsyncCommand = true
304 getdownSetAppBaseProperty = true
305 JALVIEW_VERSION=JALVIEW_VERSION+"-d${suffix}-${buildDate}"
306 install4jSuffix = "Develop ${suffix}"
307 install4jExtraScheme = "jalviewd"
308 install4jInstallerName = "${jalview_name} Develop ${suffix} Installer"
309 getdownChannelName = string("develop-${suffix}")
310 getdownChannelDir = string("${getdown_website_dir}/${getdownChannelName}")
311 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
312 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
313 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
314 channelSuffix = string(suffix)
315 backgroundImageText = true
319 reportRsyncCommand = true
320 getdownSetAppBaseProperty = true
321 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
322 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
324 install4jSuffix = "Develop"
325 install4jExtraScheme = "jalviewd"
326 install4jInstallerName = "${jalview_name} Develop Installer"
330 reportRsyncCommand = true
331 getdownSetAppBaseProperty = true
332 // Don't ignore transpile errors for release build
333 if (jalviewjs_ignore_transpile_errors.equals("true")) {
334 jalviewjs_ignore_transpile_errors = "false"
335 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
337 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
338 install4jSuffix = "Test"
339 install4jExtraScheme = "jalviewt"
340 install4jInstallerName = "${jalview_name} Test Installer"
343 case ~/^SCRATCH(|-[-\w]*)$/:
344 getdownChannelName = CHANNEL
345 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
347 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
348 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
349 reportRsyncCommand = true
350 install4jSuffix = "Scratch"
354 if (!file("${LOCALDIR}").exists()) {
355 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
357 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
358 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
360 JALVIEW_VERSION = "TEST"
361 install4jSuffix = "Test-Local"
362 install4jExtraScheme = "jalviewt"
363 install4jInstallerName = "${jalview_name} Test Installer"
366 case [ "LOCAL", "JALVIEWJS" ]:
367 JALVIEW_VERSION = "TEST"
368 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
369 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
370 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
371 install4jExtraScheme = "jalviewl"
372 install4jCheckSums = false
375 default: // something wrong specified
376 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
380 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
381 hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_data_installers_dir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
382 hugoArchiveMdFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_version_archive_dir}/Version-${JALVIEW_VERSION_UNDERSCORES}/_index.md")
383 // override getdownAppBase if requested
384 if (findProperty("getdown_appbase_override") != null) {
385 // revert to LOCAL if empty string
386 if (string(getdown_appbase_override) == "") {
387 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
388 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
389 } else if (string(getdown_appbase_override).startsWith("file://")) {
390 getdownAppBase = string(getdown_appbase_override)
391 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
393 getdownAppBase = string(getdown_appbase_override)
395 println("Overriding getdown appbase with '${getdownAppBase}'")
397 // sanitise file name for jalview launcher file for this channel
398 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
399 // install4j application and folder names
400 if (install4jSuffix == "") {
401 install4jBundleId = "${install4j_bundle_id}"
402 install4jWinApplicationId = install4j_release_win_application_id
404 applicationName = "${jalview_name} ${install4jSuffix}"
405 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
406 // add int hash of install4jSuffix to the last part of the application_id
407 def id = install4j_release_win_application_id
408 def idsplitreverse = id.split("-").reverse()
409 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
410 install4jWinApplicationId = idsplitreverse.reverse().join("-")
412 // sanitise folder and id names
413 // install4jApplicationFolder = e.g. "Jalview Build"
414 install4jApplicationFolder = applicationName
415 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
416 .replaceAll("_+", "_") // collapse __
417 install4jInternalId = applicationName
419 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
420 .replaceAll("_+", "") // collapse __
421 //.replaceAll("_*-_*", "-") // collapse _-_
422 install4jUnixApplicationFolder = applicationName
424 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
425 .replaceAll("_+", "_") // collapse __
426 .replaceAll("_*-_*", "-") // collapse _-_
429 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
430 getdownAppDir = string("${getdownAppBaseDir}/${getdownAppDistDir}")
431 //getdownJ11libDir = "${getdownAppBaseDir}/${getdown_j11lib_dir}"
432 getdownResourceDir = string("${getdownAppBaseDir}/${getdown_resource_dir}")
433 getdownInstallDir = string("${getdownAppBaseDir}/${getdown_install_dir}")
434 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
435 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
436 /* compile without modules -- using classpath libraries
437 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
438 modules_runtimeClasspath = modules_compileClasspath
444 apply plugin: "com.palantir.git-version"
445 def details = versionDetails()
446 gitHash = details.gitHash
447 gitBranch = details.branchName
448 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
449 println("Not in a git repository. Using git values from RELEASE properties file.")
450 gitHash = releaseProps.getProperty("git.hash")
451 gitBranch = releaseProps.getProperty("git.branch")
452 } catch(java.lang.RuntimeException e1) {
453 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
456 println("Using a ${CHANNEL} profile.")
458 additional_compiler_args = []
459 // configure classpath/args for j8/j11 compilation
460 if (JAVA_VERSION.equals("1.8")) {
461 JAVA_INTEGER_VERSION = string("8")
464 libDistDir = j8libDir
465 compile_source_compatibility = 1.8
466 compile_target_compatibility = 1.8
467 // these are getdown.txt properties defined dependent on the JAVA_VERSION
468 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
469 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
470 // this property is assigned below and expanded to multiple lines in the getdown task
471 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
472 // this property is for the Java library used in eclipse
473 eclipseJavaRuntimeName = string("JavaSE-1.8")
474 } else if (JAVA_VERSION.equals("11")) {
475 JAVA_INTEGER_VERSION = string("11")
477 libDistDir = j11libDir
478 compile_source_compatibility = 11
479 compile_target_compatibility = 11
480 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
481 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
482 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
483 eclipseJavaRuntimeName = string("JavaSE-11")
484 /* compile without modules -- using classpath libraries
485 additional_compiler_args += [
486 '--module-path', modules_compileClasspath.asPath,
487 '--add-modules', j11modules
490 } else if (JAVA_VERSION.equals("17")) {
491 JAVA_INTEGER_VERSION = string("17")
493 libDistDir = j17libDir
494 compile_source_compatibility = 17
495 compile_target_compatibility = 17
496 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
497 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
498 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
499 eclipseJavaRuntimeName = string("JavaSE-17")
500 /* compile without modules -- using classpath libraries
501 additional_compiler_args += [
502 '--module-path', modules_compileClasspath.asPath,
503 '--add-modules', j11modules
507 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
512 JAVA_MIN_VERSION = JAVA_VERSION
513 JAVA_MAX_VERSION = JAVA_VERSION
514 def jreInstallsDir = string(jre_installs_dir)
515 if (jreInstallsDir.startsWith("~/")) {
516 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
518 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
519 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
520 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
521 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
522 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
523 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
524 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
525 install4jConfFileName = string("jalview-install4j-conf.install4j")
526 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
527 install4jHomeDir = install4j_home_dir
528 if (install4jHomeDir.startsWith("~/")) {
529 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
532 resourceBuildDir = string("${buildDir}/resources")
533 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
534 helpBuildDir = string("${resourceBuildDir}/help_build")
535 docBuildDir = string("${resourceBuildDir}/doc_build")
537 if (buildProperties == null) {
538 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
540 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
541 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
542 helpSourceDir = string("${helpParentDir}/${help_dir}")
543 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
546 convertBinaryExpectedLocation = imagemagick_convert
547 if (convertBinaryExpectedLocation.startsWith("~/")) {
548 convertBinaryExpectedLocation = System.getProperty("user.home") + convertBinaryExpectedLocation.substring(1)
550 if (file(convertBinaryExpectedLocation).exists()) {
551 convertBinary = convertBinaryExpectedLocation
554 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
555 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
556 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
558 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
560 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
562 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
563 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
564 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
565 jalviewjsJalviewCoreHtmlFile = string("")
566 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
567 jalviewjsCoreClasslists = []
568 jalviewjsJalviewTemplateName = string(jalviewjs_name)
569 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
570 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
571 jalviewjsJ2sProps = null
572 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
574 eclipseWorkspace = null
575 eclipseBinary = string("")
576 eclipseVersion = string("")
586 outputDir = file(classesDir)
590 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
593 compileClasspath = files(sourceSets.main.java.outputDir)
594 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
596 runtimeClasspath = compileClasspath
597 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
602 srcDirs cloverInstrDir
603 outputDir = cloverClassesDir
607 srcDirs = sourceSets.main.resources.srcDirs
610 compileClasspath = files( sourceSets.clover.java.outputDir )
611 //compileClasspath += files( testClassesDir )
612 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
613 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
614 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
616 runtimeClasspath = compileClasspath
621 srcDirs testSourceDir
622 outputDir = file(testClassesDir)
626 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
629 compileClasspath = files( sourceSets.test.java.outputDir )
630 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
631 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
633 runtimeClasspath = compileClasspath
634 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
640 // eclipse project and settings files creation, also used by buildship
643 name = eclipse_project_name
645 natures 'org.eclipse.jdt.core.javanature',
646 'org.eclipse.jdt.groovy.core.groovyNature',
647 'org.eclipse.buildship.core.gradleprojectnature'
649 buildCommand 'org.eclipse.jdt.core.javabuilder'
650 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
654 //defaultOutputDir = sourceSets.main.java.outputDir
655 configurations.each{ c->
656 if (c.isCanBeResolved()) {
657 minusConfigurations += [c]
661 plusConfigurations = [ ]
665 def removeTheseToo = []
666 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
667 cp.entries.each { entry ->
668 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
669 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
670 // we add the resources and help/help dirs in as libs afterwards (see below)
671 if (entry.kind == 'src') {
672 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
673 removeTheseToo += entry
675 alreadyAddedSrcPath.putAt(entry.path, true)
680 cp.entries.removeAll(removeTheseToo)
682 //cp.entries += new Output("${eclipse_bin_dir}/main")
683 if (file(helpParentDir).isDirectory()) {
684 cp.entries += new Library(fileReference(helpParentDir))
686 if (file(resourceDir).isDirectory()) {
687 cp.entries += new Library(fileReference(resourceDir))
690 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
692 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
693 //don't want to add outputDir as eclipse is using its own output dir in bin/main
694 if (it.isDirectory() || ! it.exists()) {
695 // don't add dirs to classpath, especially if they don't exist
696 return false // groovy "continue" in .any closure
698 def itPath = it.toString()
699 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
700 // make relative path
701 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
703 if (alreadyAddedLibPath.get(itPath)) {
704 //println("Not adding duplicate entry "+itPath)
706 //println("Adding entry "+itPath)
707 cp.entries += new Library(fileReference(itPath))
708 alreadyAddedLibPath.put(itPath, true)
712 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
713 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
714 if (it.isDirectory() || ! it.exists()) {
715 // don't add dirs to classpath
716 return false // groovy "continue" in .any closure
719 def itPath = it.toString()
720 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
721 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
723 if (alreadyAddedLibPath.get(itPath)) {
726 def lib = new Library(fileReference(itPath))
727 lib.entryAttributes["test"] = "true"
729 alreadyAddedLibPath.put(itPath, true)
737 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
742 // for the IDE, use java 11 compatibility
743 sourceCompatibility = compile_source_compatibility
744 targetCompatibility = compile_target_compatibility
745 javaRuntimeName = eclipseJavaRuntimeName
747 // add in jalview project specific properties/preferences into eclipse core preferences
749 withProperties { props ->
750 def jalview_prefs = new Properties()
751 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
752 jalview_prefs.load(ins)
754 jalview_prefs.forEach { t, v ->
755 if (props.getAt(t) == null) {
759 // codestyle file -- overrides previous formatter prefs
760 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
761 if (csFile.exists()) {
762 XmlParser parser = new XmlParser()
763 def profiles = parser.parse(csFile)
764 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
765 if (profile != null) {
766 profile.'setting'.each { s ->
768 def value = s.'@value'
769 if (id != null && value != null) {
770 props.putAt(id, value)
781 // Don't want these to be activated if in headless build
782 synchronizationTasks "eclipseSynchronizationTask"
783 //autoBuildTasks "eclipseAutoBuildTask"
789 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
790 // Class to allow updating arbitrary properties files
791 class PropertiesFile extends PropertiesPersistableConfigurationObject {
792 public PropertiesFile(PropertiesTransformer t) { super(t); }
793 @Override protected void load(Properties properties) { }
794 @Override protected void store(Properties properties) { }
795 @Override protected String getDefaultResourceName() { return ""; }
796 // This is necessary, because PropertiesPersistableConfigurationObject fails
797 // if no default properties file exists.
798 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
801 // Task to update arbitrary properties files (set outputFile)
802 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
803 private final PropertiesFileContentMerger file;
804 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
805 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
806 protected void configure(PropertiesFile props) {
807 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
809 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
812 task eclipseUIPreferences(type: PropertiesFileTask) {
813 description = "Generate Eclipse additional settings"
814 def filename = "org.eclipse.jdt.ui.prefs"
815 outputFile = "$projectDir/.settings/${filename}" as File
818 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
823 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
824 description = "Generate Eclipse additional settings"
825 def filename = "org.eclipse.jdt.groovy.core.prefs"
826 outputFile = "$projectDir/.settings/${filename}" as File
829 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
834 task eclipseAllPreferences {
836 dependsOn eclipseUIPreferences
837 dependsOn eclipseGroovyCorePreferences
840 eclipseUIPreferences.mustRunAfter eclipseJdt
841 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
843 /* end of eclipse preferences hack */
851 delete cloverBuildDir
852 delete cloverReportDir
857 task cloverInstrJava(type: JavaExec) {
858 group = "Verification"
859 description = "Create clover instrumented source java files"
861 dependsOn cleanClover
863 inputs.files(sourceSets.main.allJava)
864 outputs.dir(cloverInstrDir)
866 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
867 classpath = sourceSets.clover.compileClasspath
868 main = "com.atlassian.clover.CloverInstr"
876 cloverInstrDir.getPath(),
878 def srcFiles = sourceSets.main.allJava.files
881 { file -> file.absolutePath }
884 args argsList.toArray()
887 delete cloverInstrDir
888 println("Clover: About to instrument "+srcFiles.size() +" files")
893 task cloverInstrTests(type: JavaExec) {
894 group = "Verification"
895 description = "Create clover instrumented source test files"
897 dependsOn cleanClover
899 inputs.files(testDir)
900 outputs.dir(cloverTestInstrDir)
902 classpath = sourceSets.clover.compileClasspath
903 main = "com.atlassian.clover.CloverInstr"
913 cloverTestInstrDir.getPath(),
915 args argsList.toArray()
918 delete cloverTestInstrDir
919 println("Clover: About to instrument test files")
925 group = "Verification"
926 description = "Create clover instrumented all source files"
928 dependsOn cloverInstrJava
929 dependsOn cloverInstrTests
933 cloverClasses.dependsOn cloverInstr
936 task cloverConsoleReport(type: JavaExec) {
937 group = "Verification"
938 description = "Creates clover console report"
941 file(cloverDb).exists()
944 inputs.dir cloverClassesDir
946 classpath = sourceSets.clover.runtimeClasspath
947 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
949 if (cloverreport_mem.length() > 0) {
950 maxHeapSize = cloverreport_mem
952 if (cloverreport_jvmargs.length() > 0) {
953 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
963 args argsList.toArray()
967 task cloverHtmlReport(type: JavaExec) {
968 group = "Verification"
969 description = "Creates clover HTML report"
972 file(cloverDb).exists()
975 def cloverHtmlDir = cloverReportDir
976 inputs.dir cloverClassesDir
977 outputs.dir cloverHtmlDir
979 classpath = sourceSets.clover.runtimeClasspath
980 main = "com.atlassian.clover.reporters.html.HtmlReporter"
982 if (cloverreport_mem.length() > 0) {
983 maxHeapSize = cloverreport_mem
985 if (cloverreport_jvmargs.length() > 0) {
986 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
997 if (cloverreport_html_options.length() > 0) {
998 argsList += cloverreport_html_options.split(" ")
1001 args argsList.toArray()
1005 task cloverXmlReport(type: JavaExec) {
1006 group = "Verification"
1007 description = "Creates clover XML report"
1010 file(cloverDb).exists()
1013 def cloverXmlFile = "${cloverReportDir}/clover.xml"
1014 inputs.dir cloverClassesDir
1015 outputs.file cloverXmlFile
1017 classpath = sourceSets.clover.runtimeClasspath
1018 main = "com.atlassian.clover.reporters.xml.XMLReporter"
1020 if (cloverreport_mem.length() > 0) {
1021 maxHeapSize = cloverreport_mem
1023 if (cloverreport_jvmargs.length() > 0) {
1024 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
1035 if (cloverreport_xml_options.length() > 0) {
1036 argsList += cloverreport_xml_options.split(" ")
1039 args argsList.toArray()
1044 group = "Verification"
1045 description = "Creates clover reports"
1047 dependsOn cloverXmlReport
1048 dependsOn cloverHtmlReport
1055 sourceCompatibility = compile_source_compatibility
1056 targetCompatibility = compile_target_compatibility
1057 options.compilerArgs += additional_compiler_args
1058 print ("Setting target compatibility to "+targetCompatibility+"\n")
1060 //classpath += configurations.cloverRuntime
1066 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1067 sourceCompatibility = compile_source_compatibility
1068 targetCompatibility = compile_target_compatibility
1069 options.compilerArgs = additional_compiler_args
1070 options.encoding = "UTF-8"
1072 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1079 sourceCompatibility = compile_source_compatibility
1080 targetCompatibility = compile_target_compatibility
1081 options.compilerArgs = additional_compiler_args
1083 print ("Setting target compatibility to "+targetCompatibility+"\n")
1090 delete sourceSets.main.java.outputDir
1096 dependsOn cleanClover
1098 delete sourceSets.test.java.outputDir
1103 // format is a string like date.format("dd MMMM yyyy")
1104 def getDate(format) {
1105 return date.format(format)
1109 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1110 MutableDataSet options = new MutableDataSet()
1112 def extensions = new ArrayList<>()
1113 extensions.add(AnchorLinkExtension.create())
1114 extensions.add(AutolinkExtension.create())
1115 extensions.add(StrikethroughExtension.create())
1116 extensions.add(TaskListExtension.create())
1117 extensions.add(TablesExtension.create())
1118 extensions.add(TocExtension.create())
1120 options.set(Parser.EXTENSIONS, extensions)
1122 // set GFM table parsing options
1123 options.set(TablesExtension.WITH_CAPTION, false)
1124 options.set(TablesExtension.COLUMN_SPANS, false)
1125 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1126 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1127 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1128 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1129 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1131 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1132 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1133 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1134 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1136 Parser parser = Parser.builder(options).build()
1137 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1139 mdFiles.each { mdFile ->
1140 // add table of contents
1141 def mdText = "[TOC]\n"+mdFile.text
1143 // grab the first top-level title
1145 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1146 def matcher = mdText =~ titleRegex
1147 if (matcher.size() > 0) {
1148 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1149 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1151 // or use the filename if none found
1152 if (title == null) {
1153 title = mdFile.getName()
1156 Node document = parser.parse(mdText)
1157 String htmlBody = renderer.render(document)
1158 def htmlText = '''<html>
1159 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1160 <html xmlns="http://www.w3.org/1999/xhtml">
1162 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1163 <meta http-equiv="Content-Style-Type" content="text/css" />
1164 <meta name="generator" content="flexmark" />
1166 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1168 <style type="text/css">code{white-space: pre;}</style>
1170 htmlText += ((cssFile != null) ? cssFile.text : '')
1171 htmlText += '''</head>
1174 htmlText += htmlBody
1180 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1181 def htmlFile = file(htmlFilePath)
1182 println("Creating ${htmlFilePath}")
1183 htmlFile.text = htmlText
1188 task copyDocs(type: Copy) {
1189 def inputDir = "${jalviewDir}/${doc_dir}"
1190 def outputDir = "${docBuildDir}/${doc_dir}"
1194 include('**/*.html')
1196 filter(ReplaceTokens,
1200 'Version-Rel': JALVIEW_VERSION,
1201 'Year-Rel': getDate("yyyy")
1208 exclude('**/*.html')
1213 inputs.dir(inputDir)
1214 outputs.dir(outputDir)
1218 task convertMdFiles {
1220 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1221 def cssFile = file("${jalviewDir}/${flexmark_css}")
1224 convertMdToHtml(mdFiles, cssFile)
1227 inputs.files(mdFiles)
1228 inputs.file(cssFile)
1231 mdFiles.each { mdFile ->
1232 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1233 htmlFiles.add(file(htmlFilePath))
1235 outputs.files(htmlFiles)
1239 def hugoTemplateSubstitutions(String input, Map extras=null) {
1240 def replacements = [
1241 DATE: getDate("yyyy-MM-dd"),
1242 CHANNEL: propertiesChannelName,
1243 APPLICATION_NAME: applicationName,
1245 GIT_BRANCH: gitBranch,
1246 VERSION: JALVIEW_VERSION,
1247 JAVA_VERSION: JAVA_VERSION,
1248 VERSION_UNDERSCORES: JALVIEW_VERSION_UNDERSCORES,
1253 if (extras != null) {
1254 extras.each{ k, v ->
1255 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1258 replacements.each{ k, v ->
1259 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1264 def mdFileComponents(File mdFile, def dateOnly=false) {
1267 if (mdFile.exists()) {
1268 def inFrontMatter = false
1269 def firstLine = true
1270 mdFile.eachLine { line ->
1271 if (line.matches("---")) {
1272 def prev = inFrontMatter
1273 inFrontMatter = firstLine
1274 if (inFrontMatter != prev)
1277 if (inFrontMatter) {
1279 if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
1280 map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
1281 } else if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
1282 map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
1283 } else if (m = line =~ /^channel:\s*(\S+)/) {
1284 map["channel"] = m[0][1]
1285 } else if (m = line =~ /^version:\s*(\S+)/) {
1286 map["version"] = m[0][1]
1287 } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
1288 map[ m[0][1] ] = m[0][2]
1290 if (dateOnly && map["date"] != null) {
1296 content += line+"\n"
1301 return dateOnly ? map["date"] : [map, content]
1304 task hugoTemplates {
1306 description "Create partially populated md pages for hugo website build"
1308 def hugoTemplatesDir = file("${jalviewDir}/${hugo_templates_dir}")
1309 def hugoBuildDir = "${jalviewDir}/${hugo_build_dir}"
1310 def templateFiles = fileTree(dir: hugoTemplatesDir)
1311 def releaseMdFile = file("${jalviewDir}/${releases_dir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1312 def whatsnewMdFile = file("${jalviewDir}/${whatsnew_dir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1313 def oldJvlFile = file("${jalviewDir}/${hugo_old_jvl}")
1314 def jalviewjsFile = file("${jalviewDir}/${hugo_jalviewjs}")
1317 // specific release template for version archive
1320 def givenDate = null
1321 def givenChannel = null
1322 def givenVersion = null
1323 if (CHANNEL == "RELEASE") {
1324 def (map, content) = mdFileComponents(releaseMdFile)
1325 givenDate = map.date
1326 givenChannel = map.channel
1327 givenVersion = map.version
1329 if (givenVersion != null && givenVersion != JALVIEW_VERSION) {
1330 throw new GradleException("'version' header (${givenVersion}) found in ${releaseMdFile} does not match JALVIEW_VERSION (${JALVIEW_VERSION})")
1333 if (whatsnewMdFile.exists())
1334 whatsnew = whatsnewMdFile.text
1337 def oldJvl = oldJvlFile.exists() ? oldJvlFile.collect{it} : []
1338 def jalviewjsLink = jalviewjsFile.exists() ? jalviewjsFile.collect{it} : []
1340 def changesHugo = null
1341 if (changes != null) {
1342 changesHugo = '<div class="release_notes">\n\n'
1343 def inSection = false
1344 changes.eachLine { line ->
1346 if (m = line =~ /^##([^#].*)$/) {
1348 changesHugo += "</div>\n\n"
1350 def section = m[0][1].trim()
1351 section = section.toLowerCase()
1352 section = section.replaceAll(/ +/, "_")
1353 section = section.replaceAll(/[^a-z0-9_\-]/, "")
1354 changesHugo += "<div class=\"${section}\">\n\n"
1356 } else if (m = line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
1357 def comment = m[0][2].trim()
1358 if (comment != "") {
1359 comment = comment.replaceAll('"', """)
1361 comment.eachMatch(/JAL-\d+/) { jal -> issuekeys += jal }
1362 def newline = m[0][1]
1363 if (comment.trim() != "")
1364 newline += "{{<comment>}}${comment}{{</comment>}} "
1365 newline += m[0][3].trim()
1366 if (issuekeys.size() > 0)
1367 newline += " {{< jal issue=\"${issuekeys.join(",")}\" alt=\"${comment}\" >}}"
1368 if (m[0][4] != null)
1373 changesHugo += line+"\n"
1376 changesHugo += "\n</div>\n\n"
1378 changesHugo += '</div>'
1381 templateFiles.each{ templateFile ->
1382 def newFileName = string(hugoTemplateSubstitutions(templateFile.getName()))
1383 def relPath = hugoTemplatesDir.toPath().relativize(templateFile.toPath()).getParent()
1384 def newRelPathName = hugoTemplateSubstitutions( relPath.toString() )
1386 def outPathName = string("${hugoBuildDir}/$newRelPathName")
1390 rename(templateFile.getName(), newFileName)
1394 def newFile = file("${outPathName}/${newFileName}".toString())
1395 def content = newFile.text
1396 newFile.text = hugoTemplateSubstitutions(content,
1399 CHANGES: changesHugo,
1400 DATE: givenDate == null ? "" : givenDate.format("yyyy-MM-dd"),
1401 DRAFT: givenDate == null ? "true" : "false",
1402 JALVIEWJSLINK: jalviewjsLink.contains(JALVIEW_VERSION) ? "true" : "false",
1403 JVL_HEADER: oldJvl.contains(JALVIEW_VERSION) ? "jvl: true" : ""
1410 inputs.file(oldJvlFile)
1411 inputs.dir(hugoTemplatesDir)
1412 inputs.property("JALVIEW_VERSION", { JALVIEW_VERSION })
1413 inputs.property("CHANNEL", { CHANNEL })
1416 def getMdDate(File mdFile) {
1417 return mdFileComponents(mdFile, true)
1420 def getMdSections(String content) {
1422 def sectionContent = ""
1423 def sectionName = null
1424 content.eachLine { line ->
1426 if (m = line =~ /^##([^#].*)$/) {
1427 if (sectionName != null) {
1428 sections[sectionName] = sectionContent
1432 sectionName = m[0][1].trim()
1433 sectionName = sectionName.toLowerCase()
1434 sectionName = sectionName.replaceAll(/ +/, "_")
1435 sectionName = sectionName.replaceAll(/[^a-z0-9_\-]/, "")
1436 } else if (sectionName != null) {
1437 sectionContent += line+"\n"
1440 if (sectionContent != null) {
1441 sections[sectionName] = sectionContent
1447 task copyHelp(type: Copy) {
1448 def inputDir = helpSourceDir
1449 def outputDir = "${helpBuildDir}/${help_dir}"
1453 include('**/*.html')
1457 filter(ReplaceTokens,
1461 'Version-Rel': JALVIEW_VERSION,
1462 'Year-Rel': getDate("yyyy")
1469 exclude('**/*.html')
1476 inputs.dir(inputDir)
1477 outputs.files(helpFile)
1478 outputs.dir(outputDir)
1482 task releasesTemplates {
1484 description "Recreate whatsNew.html and releases.html from markdown files and templates in help"
1488 def releasesTemplateFile = file("${jalviewDir}/${releases_template}")
1489 def whatsnewTemplateFile = file("${jalviewDir}/${whatsnew_template}")
1490 def releasesHtmlFile = file("${helpBuildDir}/${help_dir}/${releases_html}")
1491 def whatsnewHtmlFile = file("${helpBuildDir}/${help_dir}/${whatsnew_html}")
1492 def releasesMdDir = "${jalviewDir}/${releases_dir}"
1493 def whatsnewMdDir = "${jalviewDir}/${whatsnew_dir}"
1496 def releaseMdFile = file("${releasesMdDir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1497 def whatsnewMdFile = file("${whatsnewMdDir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1499 if (CHANNEL == "RELEASE") {
1500 if (!releaseMdFile.exists()) {
1501 throw new GradleException("File ${releaseMdFile} must be created for RELEASE")
1503 if (!whatsnewMdFile.exists()) {
1504 throw new GradleException("File ${whatsnewMdFile} must be created for RELEASE")
1508 def releaseFiles = fileTree(dir: releasesMdDir, include: "release-*.md")
1509 def releaseFilesDates = releaseFiles.collectEntries {
1510 [(it): getMdDate(it)]
1512 releaseFiles = releaseFiles.sort { a,b -> releaseFilesDates[a].compareTo(releaseFilesDates[b]) }
1514 def releasesTemplate = releasesTemplateFile.text
1515 def m = releasesTemplate =~ /(?s)__VERSION_LOOP_START__(.*)__VERSION_LOOP_END__/
1516 def versionTemplate = m[0][1]
1518 MutableDataSet options = new MutableDataSet()
1520 def extensions = new ArrayList<>()
1521 options.set(Parser.EXTENSIONS, extensions)
1522 options.set(Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE, true)
1524 Parser parser = Parser.builder(options).build()
1525 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1527 def actualVersions = releaseFiles.collect { rf ->
1528 def (rfMap, rfContent) = mdFileComponents(rf)
1529 return rfMap.version
1531 def versionsHtml = ""
1532 def linkedVersions = []
1533 releaseFiles.reverse().each { rFile ->
1534 def (rMap, rContent) = mdFileComponents(rFile)
1536 def versionLink = ""
1537 def partialVersion = ""
1538 def firstPart = true
1539 rMap.version.split("\\.").each { part ->
1540 def displayPart = ( firstPart ? "" : "." ) + part
1541 partialVersion += displayPart
1543 linkedVersions.contains(partialVersion)
1544 || ( actualVersions.contains(partialVersion) && partialVersion != rMap.version )
1546 versionLink += displayPart
1548 versionLink += "<a id=\"Jalview.${partialVersion}\">${displayPart}</a>"
1549 linkedVersions += partialVersion
1553 def displayDate = releaseFilesDates[rFile].format("dd/MM/yyyy")
1556 def rContentProcessed = ""
1557 rContent.eachLine { line ->
1558 if (lm = line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
1559 line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}"
1560 } else if (lm = line =~ /^###([^#]+.*)$/) {
1561 line = "_${lm[0][1].trim()}_"
1563 rContentProcessed += line + "\n"
1566 def rContentSections = getMdSections(rContentProcessed)
1567 def rVersion = versionTemplate
1568 if (rVersion != "") {
1569 def rNewFeatures = rContentSections["new_features"]
1570 def rIssuesResolved = rContentSections["issues_resolved"]
1571 Node newFeaturesNode = parser.parse(rNewFeatures)
1572 String newFeaturesHtml = renderer.render(newFeaturesNode)
1573 Node issuesResolvedNode = parser.parse(rIssuesResolved)
1574 String issuesResolvedHtml = renderer.render(issuesResolvedNode)
1575 rVersion = hugoTemplateSubstitutions(rVersion,
1577 VERSION: rMap.version,
1578 VERSION_LINK: versionLink,
1579 DISPLAY_DATE: displayDate,
1580 NEW_FEATURES: newFeaturesHtml,
1581 ISSUES_RESOLVED: issuesResolvedHtml
1584 versionsHtml += rVersion
1588 releasesTemplate = releasesTemplate.replaceAll("(?s)__VERSION_LOOP_START__.*__VERSION_LOOP_END__", versionsHtml)
1589 releasesTemplate = hugoTemplateSubstitutions(releasesTemplate)
1590 releasesHtmlFile.text = releasesTemplate
1592 if (whatsnewMdFile.exists()) {
1593 def wnDisplayDate = releaseFilesDates[releaseMdFile] != null ? releaseFilesDates[releaseMdFile].format("dd MMMM yyyy") : ""
1594 def whatsnewMd = hugoTemplateSubstitutions(whatsnewMdFile.text)
1595 Node whatsnewNode = parser.parse(whatsnewMd)
1596 String whatsnewHtml = renderer.render(whatsnewNode)
1597 whatsnewHtml = whatsnewTemplateFile.text.replaceAll("__WHATS_NEW__", whatsnewHtml)
1598 whatsnewHtmlFile.text = hugoTemplateSubstitutions(whatsnewHtml,
1600 VERSION: JALVIEW_VERSION,
1601 DISPLAY_DATE: wnDisplayDate
1604 } else if (gradle.taskGraph.hasTask(":linkCheck")) {
1605 whatsnewHtmlFile.text = "Development build " + getDate("yyyy-MM-dd HH:mm:ss")
1610 inputs.file(releasesTemplateFile)
1611 inputs.file(whatsnewTemplateFile)
1612 inputs.dir(releasesMdDir)
1613 inputs.dir(whatsnewMdDir)
1614 outputs.file(releasesHtmlFile)
1615 outputs.file(whatsnewHtmlFile)
1619 task copyResources(type: Copy) {
1621 description = "Copy (and make text substitutions in) the resources dir to the build area"
1623 def inputDir = resourceDir
1624 def outputDir = resourcesBuildDir
1628 include('**/*.html')
1630 filter(ReplaceTokens,
1634 'Version-Rel': JALVIEW_VERSION,
1635 'Year-Rel': getDate("yyyy")
1642 exclude('**/*.html')
1647 inputs.dir(inputDir)
1648 outputs.dir(outputDir)
1651 task copyChannelResources(type: Copy) {
1652 dependsOn copyResources
1654 description = "Copy the channel resources dir to the build resources area"
1656 def inputDir = "${channelDir}/${resource_dir}"
1657 def outputDir = resourcesBuildDir
1659 include(channel_props)
1660 filter(ReplaceTokens,
1664 'SUFFIX': channelSuffix
1669 exclude(channel_props)
1673 inputs.dir(inputDir)
1674 outputs.dir(outputDir)
1677 task createBuildProperties(type: WriteProperties) {
1678 dependsOn copyResources
1680 description = "Create the ${buildProperties} file"
1682 inputs.dir(sourceDir)
1683 inputs.dir(resourcesBuildDir)
1684 outputFile (buildProperties)
1685 // taking time specific comment out to allow better incremental builds
1686 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1687 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1688 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1689 property "VERSION", JALVIEW_VERSION
1690 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1691 property "JAVA_COMPILE_VERSION", JAVA_INTEGER_VERSION
1692 if (getdownSetAppBaseProperty) {
1693 property "GETDOWNAPPBASE", getdownAppBase
1694 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1696 outputs.file(outputFile)
1700 task buildIndices(type: JavaExec) {
1702 classpath = sourceSets.main.compileClasspath
1703 main = "com.sun.java.help.search.Indexer"
1704 workingDir = "${helpBuildDir}/${help_dir}"
1707 inputs.dir("${workingDir}/${argDir}")
1709 outputs.dir("${classesDir}/doc")
1710 outputs.dir("${classesDir}/help")
1711 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1712 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1713 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1714 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1715 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1716 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1719 task buildResources {
1720 dependsOn copyResources
1721 dependsOn copyChannelResources
1722 dependsOn createBuildProperties
1726 dependsOn buildResources
1729 dependsOn releasesTemplates
1730 dependsOn convertMdFiles
1731 dependsOn buildIndices
1735 compileJava.dependsOn prepare
1736 run.dependsOn compileJava
1737 //run.dependsOn prepare
1740 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1745 dependsOn cloverClasses
1747 dependsOn compileJava //?
1751 includeGroups testng_groups
1752 excludeGroups testng_excluded_groups
1754 useDefaultListeners=true
1757 maxHeapSize = "1024m"
1759 workingDir = jalviewDir
1760 def testLaf = project.findProperty("test_laf")
1761 if (testLaf != null) {
1762 println("Setting Test LaF to '${testLaf}'")
1763 systemProperty "laf", testLaf
1765 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1766 if (testHiDPIScale != null) {
1767 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1768 systemProperty "sun.java2d.uiScale", testHiDPIScale
1770 sourceCompatibility = compile_source_compatibility
1771 targetCompatibility = compile_target_compatibility
1772 jvmArgs += additional_compiler_args
1776 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1782 task compileLinkCheck(type: JavaCompile) {
1784 classpath = files("${jalviewDir}/${utils_dir}")
1785 destinationDir = file("${jalviewDir}/${utils_dir}")
1786 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1788 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1789 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1790 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1791 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1795 task linkCheck(type: JavaExec) {
1797 dependsOn compileLinkCheck
1799 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1800 classpath = files("${jalviewDir}/${utils_dir}")
1801 main = "HelpLinksChecker"
1802 workingDir = "${helpBuildDir}"
1803 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1805 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1806 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1809 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1813 inputs.dir(helpBuildDir)
1814 outputs.file(helpLinksCheckerOutFile)
1818 // import the pubhtmlhelp target
1819 ant.properties.basedir = "${jalviewDir}"
1820 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1821 ant.importBuild "${utils_dir}/publishHelp.xml"
1824 task cleanPackageDir(type: Delete) {
1826 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1836 attributes "Main-Class": main_class,
1837 "Permissions": "all-permissions",
1838 "Application-Name": applicationName,
1839 "Codebase": application_codebase,
1840 "Implementation-Version": JALVIEW_VERSION
1843 def outputDir = "${jalviewDir}/${package_dir}"
1844 destinationDirectory = file(outputDir)
1845 archiveFileName = rootProject.name+".jar"
1846 duplicatesStrategy "EXCLUDE"
1853 exclude "**/*.jar.*"
1855 inputs.dir(sourceSets.main.java.outputDir)
1856 sourceSets.main.resources.srcDirs.each{ dir ->
1859 outputs.file("${outputDir}/${archiveFileName}")
1863 task copyJars(type: Copy) {
1864 from fileTree(dir: classesDir, include: "**/*.jar").files
1865 into "${jalviewDir}/${package_dir}"
1869 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1870 task syncJars(type: Sync) {
1872 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1873 into "${jalviewDir}/${package_dir}"
1875 include jar.archiveFileName.getOrNull()
1882 description = "Put all required libraries in dist"
1883 // order of "cleanPackageDir", "copyJars", "jar" important!
1884 jar.mustRunAfter cleanPackageDir
1885 syncJars.mustRunAfter cleanPackageDir
1886 dependsOn cleanPackageDir
1889 outputs.dir("${jalviewDir}/${package_dir}")
1894 dependsOn cleanPackageDir
1901 group = "distribution"
1902 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1906 from ("${jalviewDir}/${libDistDir}") {
1910 attributes "Implementation-Version": JALVIEW_VERSION,
1911 "Application-Name": applicationName
1914 duplicatesStrategy "INCLUDE"
1916 mainClassName = shadow_jar_main_class
1918 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1922 task getdownImagesCopy() {
1923 inputs.dir getdownImagesDir
1924 outputs.dir getdownImagesBuildDir
1928 from(getdownImagesDir) {
1929 include("*getdown*.png")
1931 into getdownImagesBuildDir
1936 task getdownImagesProcess() {
1937 dependsOn getdownImagesCopy
1940 if (backgroundImageText) {
1941 if (convertBinary == null) {
1942 throw new StopExecutionException("No ImageMagick convert binary installed at '${convertBinaryExpectedLocation}'")
1944 if (!project.hasProperty("getdown_background_image_text_suffix_cmd")) {
1945 throw new StopExecutionException("No property 'getdown_background_image_text_suffix_cmd' defined. See channel_gradle.properties for channel ${CHANNEL}")
1947 fileTree(dir: getdownImagesBuildDir, include: "*background*.png").getFiles().each { file ->
1949 executable convertBinary
1952 '-font', getdown_background_image_text_font,
1953 '-fill', getdown_background_image_text_colour,
1954 '-draw', sprintf(getdown_background_image_text_suffix_cmd, channelSuffix),
1955 '-draw', sprintf(getdown_background_image_text_commit_cmd, "git-commit: ${gitHash}"),
1956 '-draw', sprintf(getdown_background_image_text_date_cmd, getDate("yyyy-MM-dd HH:mm:ss")),
1959 println("CMD=${commandLine}")
1966 task getdownImages() {
1967 dependsOn getdownImagesProcess
1970 task getdownWebsite() {
1971 group = "distribution"
1972 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1974 dependsOn getdownImages
1979 def getdownWebsiteResourceFilenames = []
1980 def getdownResourceDir = getdownResourceDir
1981 def getdownResourceFilenames = []
1984 // clean the getdown website and files dir before creating getdown folders
1985 delete getdownAppBaseDir
1986 delete getdownFilesDir
1989 from buildProperties
1990 rename(file(buildProperties).getName(), getdown_build_properties)
1993 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1996 from channelPropsFile
1997 filter(ReplaceTokens,
2001 'SUFFIX': channelSuffix
2004 into getdownAppBaseDir
2006 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
2008 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
2009 def props = project.properties.sort { it.key }
2010 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
2011 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
2013 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
2014 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
2016 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
2017 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
2019 if (getdownImagesBuildDir != null && file(getdownImagesBuildDir).exists()) {
2020 props.put("getdown_txt_ui.background_image", "${getdownImagesBuildDir}/${getdown_background_image}")
2021 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesBuildDir}/${getdown_instant_background_image}")
2022 props.put("getdown_txt_ui.error_background", "${getdownImagesBuildDir}/${getdown_error_background}")
2023 props.put("getdown_txt_ui.progress_image", "${getdownImagesBuildDir}/${getdown_progress_image}")
2024 props.put("getdown_txt_ui.icon", "${getdownImagesBuildDir}/${getdown_icon}")
2025 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesBuildDir}/${getdown_mac_dock_icon}")
2028 props.put("getdown_txt_title", jalview_name)
2029 props.put("getdown_txt_ui.name", applicationName)
2031 // start with appbase
2032 getdownTextLines += "appbase = ${getdownAppBase}"
2033 props.each{ prop, val ->
2034 if (prop.startsWith("getdown_txt_") && val != null) {
2035 if (prop.startsWith("getdown_txt_multi_")) {
2036 def key = prop.substring(18)
2037 val.split(",").each{ v ->
2038 def line = "${key} = ${v}"
2039 getdownTextLines += line
2042 // file values rationalised
2043 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
2045 if (val.indexOf('/') == 0) {
2048 } else if (val.indexOf('/') > 0) {
2049 // relative path (relative to jalviewDir)
2050 r = file( "${jalviewDir}/${val}" )
2053 val = "${getdown_resource_dir}/" + r.getName()
2054 getdownWebsiteResourceFilenames += val
2055 getdownResourceFilenames += r.getPath()
2058 if (! prop.startsWith("getdown_txt_resource")) {
2059 def line = prop.substring(12) + " = ${val}"
2060 getdownTextLines += line
2066 getdownWebsiteResourceFilenames.each{ filename ->
2067 getdownTextLines += "resource = ${filename}"
2069 getdownResourceFilenames.each{ filename ->
2072 into getdownResourceDir
2076 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
2077 getdownWrapperScripts.each{ script ->
2078 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
2082 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
2084 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
2089 fileTree(file(package_dir)).each{ f ->
2090 if (f.isDirectory()) {
2091 def files = fileTree(dir: f, include: ["*"]).getFiles()
2093 } else if (f.exists()) {
2097 def jalviewJar = jar.archiveFileName.getOrNull()
2098 // put jalview.jar first for CLASSPATH and .properties files reasons
2099 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
2100 def name = f.getName()
2101 def line = "code = ${getdownAppDistDir}/${name}"
2102 getdownTextLines += line
2109 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
2111 if (JAVA_VERSION.equals("11")) {
2112 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
2113 j11libFiles.sort().each{f ->
2114 def name = f.getName()
2115 def line = "code = ${getdown_j11lib_dir}/${name}"
2116 getdownTextLines += line
2119 into getdownJ11libDir
2125 // 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.
2126 //getdownTextLines += "class = " + file(getdownLauncher).getName()
2127 getdownTextLines += "resource = ${getdown_launcher_new}"
2128 getdownTextLines += "class = ${main_class}"
2129 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
2130 if (getdownSetAppBaseProperty) {
2131 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
2132 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
2135 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
2136 getdownTxt.write(getdownTextLines.join("\n"))
2138 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
2139 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
2140 launchJvl.write("appbase=${getdownAppBase}")
2142 // files going into the getdown website dir: getdown-launcher.jar
2144 from getdownLauncher
2145 rename(file(getdownLauncher).getName(), getdown_launcher_new)
2146 into getdownAppBaseDir
2149 // files going into the getdown website dir: getdown-launcher(-local).jar
2151 from getdownLauncher
2152 if (file(getdownLauncher).getName() != getdown_launcher) {
2153 rename(file(getdownLauncher).getName(), getdown_launcher)
2155 into getdownAppBaseDir
2158 // files going into the getdown website dir: ./install dir and files
2159 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
2162 from getdownLauncher
2163 from "${getdownAppDir}/${getdown_build_properties}"
2164 if (file(getdownLauncher).getName() != getdown_launcher) {
2165 rename(file(getdownLauncher).getName(), getdown_launcher)
2167 into getdownInstallDir
2170 // and make a copy in the getdown files dir (these are not downloaded by getdown)
2172 from getdownInstallDir
2173 into getdownFilesInstallDir
2177 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2181 from getdownLauncher
2182 from "${getdownAppBaseDir}/${getdown_build_properties}"
2183 from "${getdownAppBaseDir}/${channel_props}"
2184 if (file(getdownLauncher).getName() != getdown_launcher) {
2185 rename(file(getdownLauncher).getName(), getdown_launcher)
2187 into getdownFilesDir
2190 // and ./resource (not all downloaded by getdown)
2192 from getdownResourceDir
2193 into "${getdownFilesDir}/${getdown_resource_dir}"
2198 inputs.dir("${jalviewDir}/${package_dir}")
2200 outputs.dir(getdownAppBaseDir)
2201 outputs.dir(getdownFilesDir)
2205 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
2206 task getdownDigestDir(type: JavaExec) {
2208 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
2210 def digestDirPropertyName = "DIGESTDIR"
2212 classpath = files(getdownLauncher)
2213 def digestDir = findProperty(digestDirPropertyName)
2214 if (digestDir == null) {
2215 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
2219 main = "com.threerings.getdown.tools.Digester"
2223 task getdownDigest(type: JavaExec) {
2224 group = "distribution"
2225 description = "Digest the getdown website folder"
2226 dependsOn getdownWebsite
2228 classpath = files(getdownLauncher)
2230 main = "com.threerings.getdown.tools.Digester"
2231 args getdownAppBaseDir
2232 inputs.dir(getdownAppBaseDir)
2233 outputs.file("${getdownAppBaseDir}/digest2.txt")
2238 group = "distribution"
2239 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
2240 dependsOn getdownDigest
2242 if (reportRsyncCommand) {
2243 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
2244 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
2245 println "LIKELY RSYNC COMMAND:"
2246 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
2247 if (RUNRSYNC == "true") {
2249 commandLine "mkdir", "-p", toDir
2252 commandLine "rsync", "-avh", "--delete", fromDir, toDir
2260 task getdownArchiveBuild() {
2261 group = "distribution"
2262 description = "Put files in the archive dir to go on the website"
2264 dependsOn getdownWebsite
2266 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
2267 def vDir = "${getdownArchiveDir}/${v}"
2268 getdownFullArchiveDir = "${vDir}/getdown"
2269 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
2271 def vAltDir = "alt_${v}"
2272 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
2275 // cleanup old "old" dir
2276 delete getdownArchiveDir
2278 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
2279 getdownArchiveTxt.getParentFile().mkdirs()
2280 def getdownArchiveTextLines = []
2281 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
2285 from "${getdownAppBaseDir}/${getdownAppDistDir}"
2286 into "${getdownFullArchiveDir}/${vAltDir}"
2289 getdownTextLines.each { line ->
2290 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
2291 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
2292 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
2293 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
2294 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
2295 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
2296 // remove the existing resource = resource/ or bin/ lines
2297 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
2298 getdownArchiveTextLines += line
2302 // the resource dir -- add these files as resource lines in getdown.txt
2304 from "${archiveImagesDir}"
2305 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
2307 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
2311 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
2313 def vLaunchJvl = file(getdownVersionLaunchJvl)
2314 vLaunchJvl.getParentFile().mkdirs()
2315 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
2316 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
2317 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
2318 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
2319 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
2320 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
2322 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2324 from getdownLauncher
2325 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
2326 from "${getdownAppBaseDir}/${getdown_launcher_new}"
2327 from "${getdownAppBaseDir}/${channel_props}"
2328 if (file(getdownLauncher).getName() != getdown_launcher) {
2329 rename(file(getdownLauncher).getName(), getdown_launcher)
2331 into getdownFullArchiveDir
2337 task getdownArchiveDigest(type: JavaExec) {
2338 group = "distribution"
2339 description = "Digest the getdown archive folder"
2341 dependsOn getdownArchiveBuild
2344 classpath = files(getdownLauncher)
2345 args getdownFullArchiveDir
2347 main = "com.threerings.getdown.tools.Digester"
2348 inputs.dir(getdownFullArchiveDir)
2349 outputs.file("${getdownFullArchiveDir}/digest2.txt")
2352 task getdownArchive() {
2353 group = "distribution"
2354 description = "Build the website archive dir with getdown digest"
2356 dependsOn getdownArchiveBuild
2357 dependsOn getdownArchiveDigest
2360 tasks.withType(JavaCompile) {
2361 options.encoding = 'UTF-8'
2367 delete getdownAppBaseDir
2368 delete getdownFilesDir
2369 delete getdownArchiveDir
2375 if (file(install4jHomeDir).exists()) {
2377 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
2378 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
2379 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
2380 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
2382 installDir(file(install4jHomeDir))
2384 mediaTypes = Arrays.asList(install4j_media_types.split(","))
2388 task copyInstall4jTemplate {
2389 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
2390 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
2391 inputs.file(install4jTemplateFile)
2392 inputs.file(install4jFileAssociationsFile)
2393 inputs.property("CHANNEL", { CHANNEL })
2394 outputs.file(install4jConfFile)
2397 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
2399 // turn off code signing if no OSX_KEYPASS
2400 if (OSX_KEYPASS == "") {
2401 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
2402 codeSigning.'@macEnabled' = "false"
2404 install4jConfigXml.'**'.windows.each { windows ->
2405 windows.'@runPostProcessor' = "false"
2409 // disable install screen for OSX dmg (for 2.11.2.0)
2410 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
2411 macosArchive.attributes().remove('executeSetupApp')
2412 macosArchive.attributes().remove('setupAppId')
2415 // turn off checksum creation for LOCAL channel
2416 def e = install4jConfigXml.application[0]
2417 e.'@createChecksums' = string(install4jCheckSums)
2419 // put file association actions where placeholder action is
2420 def install4jFileAssociationsText = install4jFileAssociationsFile.text
2421 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
2422 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
2423 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
2424 def parent = a.parent()
2426 fileAssociationActions.each { faa ->
2429 // don't need to continue in .any loop once replacements have been made
2434 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
2435 // NB we're deleting the /other/ one!
2436 // Also remove the examples subdir from non-release versions
2437 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
2438 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
2439 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
2440 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
2442 // remove the examples subdir from Full File Set
2443 def files = install4jConfigXml.files[0]
2444 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
2445 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
2446 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
2447 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
2448 dirEntry.parent().remove(dirEntry)
2450 install4jConfigXml.'**'.action.any { a ->
2451 if (a.'@customizedId' == customizedIdToDelete) {
2452 def parent = a.parent()
2458 // write install4j file
2459 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2466 delete install4jConfFile
2470 task cleanInstallersDataFiles {
2471 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2472 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2473 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2475 delete installersOutputTxt
2476 delete installersSha256
2477 delete hugoDataJsonFile
2481 task install4jDMGBackgroundImageCopy {
2482 inputs.file "${install4jDMGBackgroundImageDir}/${install4jDMGBackgroundImageFile}"
2483 outputs.dir "${install4jDMGBackgroundImageBuildDir}"
2486 from(install4jDMGBackgroundImageDir) {
2487 include(install4jDMGBackgroundImageFile)
2489 into install4jDMGBackgroundImageBuildDir
2494 task install4jDMGBackgroundImageProcess {
2495 dependsOn install4jDMGBackgroundImageCopy
2498 if (backgroundImageText) {
2499 if (convertBinary == null) {
2500 throw new StopExecutionException("No ImageMagick convert binary installed at '${convertBinaryExpectedLocation}'")
2502 if (!project.hasProperty("install4j_background_image_text_suffix_cmd")) {
2503 throw new StopExecutionException("No property 'install4j_background_image_text_suffix_cmd' defined. See channel_gradle.properties for channel ${CHANNEL}")
2505 fileTree(dir: install4jDMGBackgroundImageBuildDir, include: "*.png").getFiles().each { file ->
2507 executable convertBinary
2510 '-font', install4j_background_image_text_font,
2511 '-fill', install4j_background_image_text_colour,
2512 '-draw', sprintf(install4j_background_image_text_suffix_cmd, channelSuffix),
2513 '-draw', sprintf(install4j_background_image_text_commit_cmd, "git-commit: ${gitHash}"),
2514 '-draw', sprintf(install4j_background_image_text_date_cmd, getDate("yyyy-MM-dd HH:mm:ss")),
2523 task install4jDMGBackgroundImage {
2524 dependsOn install4jDMGBackgroundImageProcess
2527 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2528 group = "distribution"
2529 description = "Create the install4j installers"
2531 dependsOn copyInstall4jTemplate
2532 dependsOn cleanInstallersDataFiles
2533 dependsOn install4jDMGBackgroundImage
2535 projectFile = install4jConfFile
2537 // create an md5 for the input files to use as version for install4j conf file
2538 def digest = MessageDigest.getInstance("MD5")
2540 (file("${install4jDir}/${install4j_template}").text +
2541 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2542 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2543 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2544 if (filesMd5.length() >= 8) {
2545 filesMd5 = filesMd5.substring(0,8)
2547 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2550 'JALVIEW_NAME': jalview_name,
2551 'JALVIEW_APPLICATION_NAME': applicationName,
2552 'JALVIEW_DIR': "../..",
2553 'OSX_KEYSTORE': OSX_KEYSTORE,
2554 'OSX_APPLEID': OSX_APPLEID,
2555 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2556 'JSIGN_SH': JSIGN_SH,
2557 'JRE_DIR': getdown_app_dir_java,
2558 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2559 'JALVIEW_VERSION': JALVIEW_VERSION,
2560 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2561 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2562 'JAVA_VERSION': JAVA_VERSION,
2563 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2564 'VERSION': JALVIEW_VERSION,
2565 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2566 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2567 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2568 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2569 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2570 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2571 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2572 'BUNDLE_ID': install4jBundleId,
2573 'INTERNAL_ID': install4jInternalId,
2574 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2575 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2576 'MACOS_DMG_BG_IMAGE': "${install4jDMGBackgroundImageBuildDir}/${install4jDMGBackgroundImageFile}",
2577 'WRAPPER_LINK': getdownWrapperLink,
2578 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2579 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2580 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2581 'INSTALLER_NAME': install4jInstallerName,
2582 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2583 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2584 'GETDOWN_FILES_DIR': getdown_files_dir,
2585 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2586 'GETDOWN_DIST_DIR': getdownAppDistDir,
2587 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2588 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2589 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2590 'BUILD_DIR': install4jBuildDir,
2591 'APPLICATION_CATEGORIES': install4j_application_categories,
2592 'APPLICATION_FOLDER': install4jApplicationFolder,
2593 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2594 'EXECUTABLE_NAME': install4jExecutableName,
2595 'EXTRA_SCHEME': install4jExtraScheme,
2596 'MAC_ICONS_FILE': install4jMacIconsFile,
2597 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2598 'PNG_ICON_FILE': install4jPngIconFile,
2599 'BACKGROUND': install4jBackground,
2603 //println("INSTALL4J VARIABLES:")
2604 //variables.each{k,v->println("${k}=${v}")}
2606 destination = "${jalviewDir}/${install4jBuildDir}"
2607 buildSelected = true
2609 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2611 disableSigning = true
2612 disableNotarization = true
2616 macKeystorePassword = OSX_KEYPASS
2619 if (OSX_ALTOOLPASS) {
2620 appleIdPassword = OSX_ALTOOLPASS
2621 disableNotarization = false
2623 disableNotarization = true
2627 println("Using projectFile "+projectFile)
2628 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2632 inputs.dir(getdownAppBaseDir)
2633 inputs.file(install4jConfFile)
2634 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2635 inputs.dir(macosJavaVMDir)
2636 inputs.dir(windowsJavaVMDir)
2637 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2640 def getDataHash(File myFile) {
2641 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2642 return myFile.exists()
2644 "file" : myFile.getName(),
2645 "filesize" : myFile.length(),
2646 "sha256" : hash.toString()
2651 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2653 "channel" : getdownChannelName,
2654 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2655 "git-commit" : "${gitHash} [${gitBranch}]",
2656 "version" : JALVIEW_VERSION
2658 // install4j installer files
2659 if (installersOutputTxt.exists()) {
2661 installersOutputTxt.readLines().each { def line ->
2662 if (line.startsWith("#")) {
2665 line.replaceAll("\n","")
2666 def vals = line.split("\t")
2667 def filename = vals[3]
2668 def filesize = file(filename).length()
2669 filename = filename.replaceAll(/^.*\//, "")
2670 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2671 idHash."${filename}" = vals[0]
2673 if (install4jCheckSums && installersSha256.exists()) {
2674 installersSha256.readLines().each { def line ->
2675 if (line.startsWith("#")) {
2678 line.replaceAll("\n","")
2679 def vals = line.split(/\s+\*?/)
2680 def filename = vals[1]
2681 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2687 "JAR": shadowJar.archiveFile, // executable JAR
2688 "JVL": getdownVersionLaunchJvl, // version JVL
2689 "SOURCE": sourceDist.archiveFile // source TGZ
2690 ].each { key, value ->
2691 def file = file(value)
2692 if (file.exists()) {
2693 def fileHash = getDataHash(file)
2694 if (fileHash != null) {
2695 hash."${key}" = fileHash;
2699 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2702 task staticMakeInstallersJsonFile {
2704 def output = findProperty("i4j_output")
2705 def sha256 = findProperty("i4j_sha256")
2706 def json = findProperty("i4j_json")
2707 if (output == null || sha256 == null || json == null) {
2708 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2710 writeDataJsonFile(file(output), file(sha256), file(json))
2715 dependsOn installerFiles
2721 eclipse().configFile(eclipse_codestyle_file)
2725 task createSourceReleaseProperties(type: WriteProperties) {
2726 group = "distribution"
2727 description = "Create the source RELEASE properties file"
2729 def sourceTarBuildDir = "${buildDir}/sourceTar"
2730 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2731 outputFile (sourceReleasePropertiesFile)
2734 releaseProps.each{ key, val -> property key, val }
2735 property "git.branch", gitBranch
2736 property "git.hash", gitHash
2739 outputs.file(outputFile)
2742 task sourceDist(type: Tar) {
2743 group "distribution"
2744 description "Create a source .tar.gz file for distribution"
2746 dependsOn createBuildProperties
2747 dependsOn convertMdFiles
2748 dependsOn eclipseAllPreferences
2749 dependsOn createSourceReleaseProperties
2752 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2753 archiveFileName = outputFileName
2755 compression Compression.GZIP
2770 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2772 "utils/InstallAnywhere",
2787 "gradle.properties",
2799 ".settings/org.eclipse.buildship.core.prefs",
2800 ".settings/org.eclipse.jdt.core.prefs"
2804 exclude (EXCLUDE_FILES)
2805 include (PROCESS_FILES)
2806 filter(ReplaceTokens,
2810 'Version-Rel': JALVIEW_VERSION,
2811 'Year-Rel': getDate("yyyy")
2816 exclude (EXCLUDE_FILES)
2817 exclude (PROCESS_FILES)
2818 exclude ("appletlib")
2819 exclude ("**/*locales")
2820 exclude ("*locales/**")
2821 exclude ("utils/InstallAnywhere")
2823 exclude (getdown_files_dir)
2824 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2825 //exclude (getdown_website_dir)
2826 //exclude (getdown_archive_dir)
2828 // exluding these as not using jars as modules yet
2829 exclude ("${j11modDir}/**/*.jar")
2832 include(INCLUDE_FILES)
2834 // from (jalviewDir) {
2835 // // explicit includes for stuff that seemed to not get included
2836 // include(fileTree("test/**/*."))
2837 // exclude(EXCLUDE_FILES)
2838 // exclude(PROCESS_FILES)
2841 from(file(buildProperties).getParent()) {
2842 include(file(buildProperties).getName())
2843 rename(file(buildProperties).getName(), "build_properties")
2845 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2849 def sourceTarBuildDir = "${buildDir}/sourceTar"
2850 from(sourceTarBuildDir) {
2851 // this includes the appended RELEASE properties file
2855 task dataInstallersJson {
2857 description "Create the installers-VERSION.json data file for installer files created"
2859 mustRunAfter installers
2860 mustRunAfter shadowJar
2861 mustRunAfter sourceDist
2862 mustRunAfter getdownArchive
2864 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2865 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2867 if (installersOutputTxt.exists()) {
2868 inputs.file(installersOutputTxt)
2870 if (install4jCheckSums && installersSha256.exists()) {
2871 inputs.file(installersSha256)
2874 shadowJar.archiveFile, // executable JAR
2875 getdownVersionLaunchJvl, // version JVL
2876 sourceDist.archiveFile // source TGZ
2877 ].each { fileName ->
2878 if (file(fileName).exists()) {
2879 inputs.file(fileName)
2883 outputs.file(hugoDataJsonFile)
2886 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2892 description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'."
2895 dependsOn pubhtmlhelp
2897 inputs.dir("${helpBuildDir}/${help_dir}")
2898 outputs.dir("${buildDir}/distributions/${help_dir}")
2902 task j2sSetHeadlessBuild {
2909 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2911 description "Enable the alternative J2S Config file for headless build"
2913 outputFile = jalviewjsJ2sSettingsFileName
2914 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2915 def j2sProps = new Properties()
2916 if (j2sPropsFile.exists()) {
2918 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2919 j2sProps.load(j2sPropsFileFIS)
2920 j2sPropsFileFIS.close()
2922 j2sProps.each { prop, val ->
2925 } catch (Exception e) {
2926 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2930 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2931 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2936 task jalviewjsSetEclipseWorkspace {
2937 def propKey = "jalviewjs_eclipse_workspace"
2939 if (project.hasProperty(propKey)) {
2940 propVal = project.getProperty(propKey)
2941 if (propVal.startsWith("~/")) {
2942 propVal = System.getProperty("user.home") + propVal.substring(1)
2945 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2946 def propsFile = file(propsFileName)
2947 def eclipseWsDir = propVal
2948 def props = new Properties()
2950 def writeProps = true
2951 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2952 def ins = new FileInputStream(propsFileName)
2955 if (props.getProperty(propKey, null) != null) {
2956 eclipseWsDir = props.getProperty(propKey)
2961 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2962 def tempDir = File.createTempDir()
2963 eclipseWsDir = tempDir.getAbsolutePath()
2966 eclipseWorkspace = file(eclipseWsDir)
2969 // do not run a headless transpile when we claim to be in Eclipse
2971 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2972 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2974 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2978 props.setProperty(propKey, eclipseWsDir)
2979 propsFile.parentFile.mkdirs()
2980 def bytes = new ByteArrayOutputStream()
2981 props.store(bytes, null)
2982 def propertiesString = bytes.toString()
2983 propsFile.text = propertiesString
2989 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2992 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2993 outputs.file(propsFileName)
2994 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2998 task jalviewjsEclipsePaths {
3001 def eclipseRoot = jalviewjs_eclipse_root
3002 if (eclipseRoot.startsWith("~/")) {
3003 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
3005 if (OperatingSystem.current().isMacOsX()) {
3006 eclipseRoot += "/Eclipse.app"
3007 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
3008 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
3009 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
3010 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
3011 eclipseRoot += "/eclipse"
3013 eclipseBinary = "${eclipseRoot}/eclipse.exe"
3014 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
3015 } else { // linux or unix
3016 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
3017 eclipseRoot += "/eclipse"
3018 println("eclipseDir exists")
3020 eclipseBinary = "${eclipseRoot}/eclipse"
3021 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
3024 eclipseVersion = "4.13" // default
3025 def assumedVersion = true
3026 if (file(eclipseProduct).exists()) {
3027 def fis = new FileInputStream(eclipseProduct)
3028 def props = new Properties()
3030 eclipseVersion = props.getProperty("version")
3032 assumedVersion = false
3035 def propKey = "eclipse_debug"
3036 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
3039 // do not run a headless transpile when we claim to be in Eclipse
3041 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3042 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3044 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3047 if (!assumedVersion) {
3048 println("ECLIPSE VERSION=${eclipseVersion}")
3054 task printProperties {
3056 description "Output to console all System.properties"
3058 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
3064 dependsOn eclipseProject
3065 dependsOn eclipseClasspath
3066 dependsOn eclipseJdt
3070 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
3071 task jalviewjsEclipseCopyDropins(type: Copy) {
3072 dependsOn jalviewjsEclipsePaths
3074 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
3075 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
3076 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
3083 // this eclipse -clean doesn't actually work
3084 task jalviewjsCleanEclipse(type: Exec) {
3085 dependsOn eclipseSetup
3086 dependsOn jalviewjsEclipsePaths
3087 dependsOn jalviewjsEclipseCopyDropins
3089 executable(eclipseBinary)
3090 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
3096 def inputString = """exit
3099 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
3100 standardInput = inputByteStream
3103 /* not really working yet
3104 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
3108 task jalviewjsTransferUnzipSwingJs {
3109 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
3113 from zipTree(file_zip)
3114 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3118 inputs.file file_zip
3119 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3123 task jalviewjsTransferUnzipLib {
3124 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
3127 zipFiles.each { file_zip ->
3129 from zipTree(file_zip)
3130 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3135 inputs.files zipFiles
3136 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3140 task jalviewjsTransferUnzipAllLibs {
3141 dependsOn jalviewjsTransferUnzipSwingJs
3142 dependsOn jalviewjsTransferUnzipLib
3146 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
3148 description "Create the alternative j2s file from the j2s.* properties"
3150 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
3151 def siteDirProperty = "j2s.site.directory"
3152 def setSiteDir = false
3153 jalviewjsJ2sProps.each { prop, val ->
3155 if (prop == siteDirProperty) {
3156 if (!(val.startsWith('/') || val.startsWith("file://") )) {
3157 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3163 if (!setSiteDir) { // default site location, don't override specifically set property
3164 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3167 outputFile = jalviewjsJ2sAltSettingsFileName
3170 inputs.properties(jalviewjsJ2sProps)
3171 outputs.file(jalviewjsJ2sAltSettingsFileName)
3176 task jalviewjsEclipseSetup {
3177 dependsOn jalviewjsEclipseCopyDropins
3178 dependsOn jalviewjsSetEclipseWorkspace
3179 dependsOn jalviewjsCreateJ2sSettings
3183 task jalviewjsSyncAllLibs (type: Sync) {
3184 dependsOn jalviewjsTransferUnzipAllLibs
3185 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3186 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3187 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3191 def outputFiles = []
3192 rename { filename ->
3193 outputFiles += "${outputDir}/${filename}"
3200 // should this be exclude really ?
3201 duplicatesStrategy "INCLUDE"
3203 outputs.files outputFiles
3204 inputs.files inputFiles
3208 task jalviewjsSyncResources (type: Sync) {
3209 dependsOn buildResources
3211 def inputFiles = fileTree(dir: resourcesBuildDir)
3212 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3216 def outputFiles = []
3217 rename { filename ->
3218 outputFiles += "${outputDir}/${filename}"
3224 outputs.files outputFiles
3225 inputs.files inputFiles
3229 task jalviewjsSyncSiteResources (type: Sync) {
3230 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3231 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3235 def outputFiles = []
3236 rename { filename ->
3237 outputFiles += "${outputDir}/${filename}"
3243 outputs.files outputFiles
3244 inputs.files inputFiles
3248 task jalviewjsSyncBuildProperties (type: Sync) {
3249 dependsOn createBuildProperties
3250 def inputFiles = [file(buildProperties)]
3251 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3255 def outputFiles = []
3256 rename { filename ->
3257 outputFiles += "${outputDir}/${filename}"
3263 outputs.files outputFiles
3264 inputs.files inputFiles
3268 task jalviewjsProjectImport(type: Exec) {
3269 dependsOn eclipseSetup
3270 dependsOn jalviewjsEclipsePaths
3271 dependsOn jalviewjsEclipseSetup
3274 // do not run a headless import when we claim to be in Eclipse
3276 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3277 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3279 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3283 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3284 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3285 executable(eclipseBinary)
3286 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3290 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3292 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3293 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3296 inputs.file("${jalviewDir}/.project")
3297 outputs.upToDateWhen {
3298 file(projdir).exists()
3303 task jalviewjsTranspile(type: Exec) {
3304 dependsOn jalviewjsEclipseSetup
3305 dependsOn jalviewjsProjectImport
3306 dependsOn jalviewjsEclipsePaths
3308 dependsOn jalviewjsEnableAltFileProperty
3312 // do not run a headless transpile when we claim to be in Eclipse
3314 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3315 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3317 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3321 executable(eclipseBinary)
3322 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3326 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3328 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3329 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3335 stdout = new ByteArrayOutputStream()
3336 stderr = new ByteArrayOutputStream()
3338 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3339 def logOutFile = file(logOutFileName)
3340 logOutFile.createNewFile()
3341 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3342 BINARY: ${eclipseBinary}
3343 VERSION: ${eclipseVersion}
3344 WORKSPACE: ${eclipseWorkspace}
3345 DEBUG: ${eclipseDebug}
3348 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3349 // combine stdout and stderr
3350 def logErrFOS = logOutFOS
3352 if (jalviewjs_j2s_to_console.equals("true")) {
3353 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3354 new org.apache.tools.ant.util.TeeOutputStream(
3358 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3359 new org.apache.tools.ant.util.TeeOutputStream(
3364 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3367 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3374 if (stdout.toString().contains("Error processing ")) {
3375 // j2s did not complete transpile
3376 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3377 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3378 println("IGNORING TRANSPILE ERRORS")
3379 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3381 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3386 inputs.dir("${jalviewDir}/${sourceDir}")
3387 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3388 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3392 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3394 def stdout = new ByteArrayOutputStream()
3395 def stderr = new ByteArrayOutputStream()
3397 def coreFile = file(jsfile)
3399 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3401 logOutFile.createNewFile()
3402 logOutFile.append(msg+"\n")
3404 def coreTop = file(prefixFile)
3405 def coreBottom = file(suffixFile)
3406 coreFile.getParentFile().mkdirs()
3407 coreFile.createNewFile()
3408 coreFile.write( coreTop.getText("UTF-8") )
3412 def t = f.getText("UTF-8")
3413 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3414 coreFile.append( t )
3416 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3418 logOutFile.append(msg+"\n")
3421 coreFile.append( coreBottom.getText("UTF-8") )
3423 msg = "Generating ${zjsfile}"
3425 logOutFile.append(msg+"\n")
3426 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3427 def logErrFOS = logOutFOS
3430 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3431 main = "com.google.javascript.jscomp.CommandLineRunner"
3432 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3433 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3436 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3438 logOutFile.append(msg+"\n")
3440 if (logOutConsole) {
3441 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3442 new org.apache.tools.ant.util.TeeOutputStream(
3446 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3447 new org.apache.tools.ant.util.TeeOutputStream(
3452 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3455 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3462 logOutFile.append(msg+"\n")
3466 task jalviewjsBuildAllCores {
3468 description "Build the core js lib closures listed in the classlists dir"
3469 dependsOn jalviewjsTranspile
3470 dependsOn jalviewjsTransferUnzipSwingJs
3472 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3473 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3474 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3475 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3476 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3477 def prefixFile = "${jsDir}/core/coretop2.js"
3478 def suffixFile = "${jsDir}/core/corebottom2.js"
3480 inputs.file prefixFile
3481 inputs.file suffixFile
3483 def classlistFiles = []
3484 // add the classlists found int the jalviewjs_classlists_dir
3485 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3487 def name = file.getName() - ".txt"
3494 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3495 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3496 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3498 jalviewjsCoreClasslists = []
3500 classlistFiles.each {
3503 def file = hash['file']
3504 if (! file.exists()) {
3505 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3506 return false // this is a "continue" in groovy .each closure
3508 def name = hash['name']
3510 name = file.getName() - ".txt"
3518 def list = fileTree(dir: j2sDir, includes: filelist)
3520 def jsfile = "${outputDir}/core${name}.js"
3521 def zjsfile = "${outputDir}/core${name}.z.js"
3523 jalviewjsCoreClasslists += [
3532 outputs.file(jsfile)
3533 outputs.file(zjsfile)
3536 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3537 def stevesoftClasslistName = "_stevesoft"
3538 def stevesoftClasslist = [
3539 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3540 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3541 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3542 'name': stevesoftClasslistName
3544 jalviewjsCoreClasslists += stevesoftClasslist
3545 inputs.files(stevesoftClasslist['list'])
3546 outputs.file(stevesoftClasslist['jsfile'])
3547 outputs.file(stevesoftClasslist['zjsfile'])
3550 def allClasslistName = "_all"
3551 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3552 allJsFiles += fileTree(
3556 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3557 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3558 "**/org/jmol/export/JSExporter.js"
3561 allJsFiles += fileTree(
3565 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3566 "**/sun/misc/Unsafe.js",
3567 "**/swingjs/jquery/jquery-editable-select.js",
3568 "**/swingjs/jquery/j2sComboBox.js",
3569 "**/sun/misc/FloatingDecimal.js"
3572 def allClasslist = [
3573 'jsfile': "${outputDir}/core${allClasslistName}.js",
3574 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3576 'name': allClasslistName
3578 // not including this version of "all" core at the moment
3579 //jalviewjsCoreClasslists += allClasslist
3580 inputs.files(allClasslist['list'])
3581 outputs.file(allClasslist['jsfile'])
3582 outputs.file(allClasslist['zjsfile'])
3585 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3586 logOutFile.getParentFile().mkdirs()
3587 logOutFile.createNewFile()
3588 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3590 jalviewjsCoreClasslists.each {
3591 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3598 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3601 into file(outputFile).getParentFile()
3602 rename { filename ->
3603 if (filename.equals(inputFile.getName())) {
3604 return file(outputFile).getName()
3608 filter(ReplaceTokens,
3612 'MAIN': '"'+main_class+'"',
3614 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3615 'COREKEY': jalviewjs_core_key,
3616 'CORENAME': coreName
3623 task jalviewjsPublishCoreTemplates {
3624 dependsOn jalviewjsBuildAllCores
3625 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3626 def inputFile = file(inputFileName)
3627 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3629 def outputFiles = []
3630 jalviewjsCoreClasslists.each { cl ->
3631 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3632 cl['outputfile'] = outputFile
3633 outputFiles += outputFile
3637 jalviewjsCoreClasslists.each { cl ->
3638 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3641 inputs.file(inputFile)
3642 outputs.files(outputFiles)
3646 task jalviewjsSyncCore (type: Sync) {
3647 dependsOn jalviewjsBuildAllCores
3648 dependsOn jalviewjsPublishCoreTemplates
3649 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3650 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3654 def outputFiles = []
3655 rename { filename ->
3656 outputFiles += "${outputDir}/${filename}"
3662 outputs.files outputFiles
3663 inputs.files inputFiles
3667 // this Copy version of TransferSiteJs will delete anything else in the target dir
3668 task jalviewjsCopyTransferSiteJs(type: Copy) {
3669 dependsOn jalviewjsTranspile
3670 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3671 into "${jalviewDir}/${jalviewjsSiteDir}"
3675 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3676 task jalviewjsSyncTransferSiteJs(type: Sync) {
3677 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3679 into "${jalviewDir}/${jalviewjsSiteDir}"
3686 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3687 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3688 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3689 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3691 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3692 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3693 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3694 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3697 task jalviewjsPrepareSite {
3699 description "Prepares the website folder including unzipping files and copying resources"
3700 dependsOn jalviewjsSyncAllLibs
3701 dependsOn jalviewjsSyncResources
3702 dependsOn jalviewjsSyncSiteResources
3703 dependsOn jalviewjsSyncBuildProperties
3704 dependsOn jalviewjsSyncCore
3708 task jalviewjsBuildSite {
3710 description "Builds the whole website including transpiled code"
3711 dependsOn jalviewjsCopyTransferSiteJs
3712 dependsOn jalviewjsPrepareSite
3716 task cleanJalviewjsTransferSite {
3718 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3719 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3720 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3721 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3726 task cleanJalviewjsSite {
3727 dependsOn cleanJalviewjsTransferSite
3729 delete "${jalviewDir}/${jalviewjsSiteDir}"
3734 task jalviewjsSiteTar(type: Tar) {
3736 description "Creates a tar.gz file for the website"
3737 dependsOn jalviewjsBuildSite
3738 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3739 archiveFileName = outputFilename
3741 compression Compression.GZIP
3743 from "${jalviewDir}/${jalviewjsSiteDir}"
3744 into jalviewjs_site_dir // this is inside the tar file
3746 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3750 task jalviewjsServer {
3752 def filename = "jalviewjsTest.html"
3753 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3754 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3759 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3760 factory = f.newInstance()
3761 } catch (ClassNotFoundException e) {
3762 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3764 def port = Integer.valueOf(jalviewjs_server_port)
3769 while(port < start+1000 && !running) {
3771 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3772 jalviewjsServer = factory.start(doc_root, port)
3774 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3775 println("SERVER STARTED with document root ${doc_root}.")
3776 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3777 println("For debug: "+url+"?j2sdebug")
3778 println("For verbose: "+url+"?j2sverbose")
3779 } catch (Exception e) {
3784 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3785 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3786 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3788 jalviewjsCoreClasslists.each { cl ->
3789 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3791 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3793 println("For core ${cl.name}: "+urlcore)
3796 file(htmlFile).text = htmlText
3799 outputs.file(htmlFile)
3800 outputs.upToDateWhen({false})
3804 task cleanJalviewjsAll {
3806 description "Delete all configuration and build artifacts to do with JalviewJS build"
3807 dependsOn cleanJalviewjsSite
3808 dependsOn jalviewjsEclipsePaths
3811 delete "${jalviewDir}/${jalviewjsBuildDir}"
3812 delete "${jalviewDir}/${eclipse_bin_dir}"
3813 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3814 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3816 delete jalviewjsJ2sAltSettingsFileName
3819 outputs.upToDateWhen( { false } )
3823 task jalviewjsIDE_checkJ2sPlugin {
3824 group "00 JalviewJS in Eclipse"
3825 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3828 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3829 def j2sPluginFile = file(j2sPlugin)
3830 def eclipseHome = System.properties["eclipse.home.location"]
3831 if (eclipseHome == null || ! IN_ECLIPSE) {
3832 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3834 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3835 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3836 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3837 eclipseJ2sPluginDirs += altPluginsDir
3839 def foundPlugin = false
3840 def j2sPluginFileName = j2sPluginFile.getName()
3841 def eclipseJ2sPlugin
3842 def eclipseJ2sPluginFile
3843 eclipseJ2sPluginDirs.any { dir ->
3844 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3845 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3846 if (eclipseJ2sPluginFile.exists()) {
3852 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3853 System.err.println(msg)
3854 throw new StopExecutionException(msg)
3857 def digest = MessageDigest.getInstance("MD5")
3859 digest.update(j2sPluginFile.text.bytes)
3860 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3862 digest.update(eclipseJ2sPluginFile.text.bytes)
3863 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3865 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3866 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3867 System.err.println(msg)
3868 throw new StopExecutionException(msg)
3870 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3876 task jalviewjsIDE_copyJ2sPlugin {
3877 group "00 JalviewJS in Eclipse"
3878 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3881 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3882 def j2sPluginFile = file(j2sPlugin)
3883 def eclipseHome = System.properties["eclipse.home.location"]
3884 if (eclipseHome == null || ! IN_ECLIPSE) {
3885 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3887 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3888 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3889 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3890 System.err.println(msg)
3893 eclipseJ2sPluginFile.getParentFile().mkdirs()
3894 into eclipseJ2sPluginFile.getParent()
3900 task jalviewjsIDE_j2sFile {
3901 group "00 JalviewJS in Eclipse"
3902 description "Creates the .j2s file"
3903 dependsOn jalviewjsCreateJ2sSettings
3907 task jalviewjsIDE_SyncCore {
3908 group "00 JalviewJS in Eclipse"
3909 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3910 dependsOn jalviewjsSyncCore
3914 task jalviewjsIDE_SyncSiteAll {
3915 dependsOn jalviewjsSyncAllLibs
3916 dependsOn jalviewjsSyncResources
3917 dependsOn jalviewjsSyncSiteResources
3918 dependsOn jalviewjsSyncBuildProperties
3922 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3925 task jalviewjsIDE_PrepareSite {
3926 group "00 JalviewJS in Eclipse"
3927 description "Sync libs and resources to site dir, but not closure cores"
3929 dependsOn jalviewjsIDE_SyncSiteAll
3930 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3934 task jalviewjsIDE_AssembleSite {
3935 group "00 JalviewJS in Eclipse"
3936 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3937 dependsOn jalviewjsPrepareSite
3941 task jalviewjsIDE_SiteClean {
3942 group "00 JalviewJS in Eclipse"
3943 description "Deletes the Eclipse transpiled site"
3944 dependsOn cleanJalviewjsSite
3948 task jalviewjsIDE_Server {
3949 group "00 JalviewJS in Eclipse"
3950 description "Starts a webserver on localhost to test the website"
3951 dependsOn jalviewjsServer
3955 // buildship runs this at import or gradle refresh
3956 task eclipseSynchronizationTask {
3957 //dependsOn eclipseSetup
3958 dependsOn createBuildProperties
3960 dependsOn jalviewjsIDE_j2sFile
3961 dependsOn jalviewjsIDE_checkJ2sPlugin
3962 dependsOn jalviewjsIDE_PrepareSite
3967 // buildship runs this at build time or project refresh
3968 task eclipseAutoBuildTask {
3969 //dependsOn jalviewjsIDE_checkJ2sPlugin
3970 //dependsOn jalviewjsIDE_PrepareSite
3976 description "Build the site"
3977 dependsOn jalviewjsBuildSite