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")),
1965 task getdownImages() {
1966 dependsOn getdownImagesProcess
1969 task getdownWebsite() {
1970 group = "distribution"
1971 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1973 dependsOn getdownImages
1978 def getdownWebsiteResourceFilenames = []
1979 def getdownResourceDir = getdownResourceDir
1980 def getdownResourceFilenames = []
1983 // clean the getdown website and files dir before creating getdown folders
1984 delete getdownAppBaseDir
1985 delete getdownFilesDir
1988 from buildProperties
1989 rename(file(buildProperties).getName(), getdown_build_properties)
1992 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1995 from channelPropsFile
1996 filter(ReplaceTokens,
2000 'SUFFIX': channelSuffix
2003 into getdownAppBaseDir
2005 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
2007 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
2008 def props = project.properties.sort { it.key }
2009 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
2010 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
2012 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
2013 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
2015 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
2016 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
2018 if (getdownImagesBuildDir != null && file(getdownImagesBuildDir).exists()) {
2019 props.put("getdown_txt_ui.background_image", "${getdownImagesBuildDir}/${getdown_background_image}")
2020 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesBuildDir}/${getdown_instant_background_image}")
2021 props.put("getdown_txt_ui.error_background", "${getdownImagesBuildDir}/${getdown_error_background}")
2022 props.put("getdown_txt_ui.progress_image", "${getdownImagesBuildDir}/${getdown_progress_image}")
2023 props.put("getdown_txt_ui.icon", "${getdownImagesBuildDir}/${getdown_icon}")
2024 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesBuildDir}/${getdown_mac_dock_icon}")
2027 props.put("getdown_txt_title", jalview_name)
2028 props.put("getdown_txt_ui.name", applicationName)
2030 // start with appbase
2031 getdownTextLines += "appbase = ${getdownAppBase}"
2032 props.each{ prop, val ->
2033 if (prop.startsWith("getdown_txt_") && val != null) {
2034 if (prop.startsWith("getdown_txt_multi_")) {
2035 def key = prop.substring(18)
2036 val.split(",").each{ v ->
2037 def line = "${key} = ${v}"
2038 getdownTextLines += line
2041 // file values rationalised
2042 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
2044 if (val.indexOf('/') == 0) {
2047 } else if (val.indexOf('/') > 0) {
2048 // relative path (relative to jalviewDir)
2049 r = file( "${jalviewDir}/${val}" )
2052 val = "${getdown_resource_dir}/" + r.getName()
2053 getdownWebsiteResourceFilenames += val
2054 getdownResourceFilenames += r.getPath()
2057 if (! prop.startsWith("getdown_txt_resource")) {
2058 def line = prop.substring(12) + " = ${val}"
2059 getdownTextLines += line
2065 getdownWebsiteResourceFilenames.each{ filename ->
2066 getdownTextLines += "resource = ${filename}"
2068 getdownResourceFilenames.each{ filename ->
2071 into getdownResourceDir
2075 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
2076 getdownWrapperScripts.each{ script ->
2077 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
2081 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
2083 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
2088 fileTree(file(package_dir)).each{ f ->
2089 if (f.isDirectory()) {
2090 def files = fileTree(dir: f, include: ["*"]).getFiles()
2092 } else if (f.exists()) {
2096 def jalviewJar = jar.archiveFileName.getOrNull()
2097 // put jalview.jar first for CLASSPATH and .properties files reasons
2098 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
2099 def name = f.getName()
2100 def line = "code = ${getdownAppDistDir}/${name}"
2101 getdownTextLines += line
2108 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
2110 if (JAVA_VERSION.equals("11")) {
2111 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
2112 j11libFiles.sort().each{f ->
2113 def name = f.getName()
2114 def line = "code = ${getdown_j11lib_dir}/${name}"
2115 getdownTextLines += line
2118 into getdownJ11libDir
2124 // 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.
2125 //getdownTextLines += "class = " + file(getdownLauncher).getName()
2126 getdownTextLines += "resource = ${getdown_launcher_new}"
2127 getdownTextLines += "class = ${main_class}"
2128 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
2129 if (getdownSetAppBaseProperty) {
2130 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
2131 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
2134 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
2135 getdownTxt.write(getdownTextLines.join("\n"))
2137 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
2138 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
2139 launchJvl.write("appbase=${getdownAppBase}")
2141 // files going into the getdown website dir: getdown-launcher.jar
2143 from getdownLauncher
2144 rename(file(getdownLauncher).getName(), getdown_launcher_new)
2145 into getdownAppBaseDir
2148 // files going into the getdown website dir: getdown-launcher(-local).jar
2150 from getdownLauncher
2151 if (file(getdownLauncher).getName() != getdown_launcher) {
2152 rename(file(getdownLauncher).getName(), getdown_launcher)
2154 into getdownAppBaseDir
2157 // files going into the getdown website dir: ./install dir and files
2158 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
2161 from getdownLauncher
2162 from "${getdownAppDir}/${getdown_build_properties}"
2163 if (file(getdownLauncher).getName() != getdown_launcher) {
2164 rename(file(getdownLauncher).getName(), getdown_launcher)
2166 into getdownInstallDir
2169 // and make a copy in the getdown files dir (these are not downloaded by getdown)
2171 from getdownInstallDir
2172 into getdownFilesInstallDir
2176 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2180 from getdownLauncher
2181 from "${getdownAppBaseDir}/${getdown_build_properties}"
2182 from "${getdownAppBaseDir}/${channel_props}"
2183 if (file(getdownLauncher).getName() != getdown_launcher) {
2184 rename(file(getdownLauncher).getName(), getdown_launcher)
2186 into getdownFilesDir
2189 // and ./resource (not all downloaded by getdown)
2191 from getdownResourceDir
2192 into "${getdownFilesDir}/${getdown_resource_dir}"
2197 inputs.dir("${jalviewDir}/${package_dir}")
2199 outputs.dir(getdownAppBaseDir)
2200 outputs.dir(getdownFilesDir)
2204 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
2205 task getdownDigestDir(type: JavaExec) {
2207 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
2209 def digestDirPropertyName = "DIGESTDIR"
2211 classpath = files(getdownLauncher)
2212 def digestDir = findProperty(digestDirPropertyName)
2213 if (digestDir == null) {
2214 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
2218 main = "com.threerings.getdown.tools.Digester"
2222 task getdownDigest(type: JavaExec) {
2223 group = "distribution"
2224 description = "Digest the getdown website folder"
2225 dependsOn getdownWebsite
2227 classpath = files(getdownLauncher)
2229 main = "com.threerings.getdown.tools.Digester"
2230 args getdownAppBaseDir
2231 inputs.dir(getdownAppBaseDir)
2232 outputs.file("${getdownAppBaseDir}/digest2.txt")
2237 group = "distribution"
2238 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
2239 dependsOn getdownDigest
2241 if (reportRsyncCommand) {
2242 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
2243 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
2244 println "LIKELY RSYNC COMMAND:"
2245 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
2246 if (RUNRSYNC == "true") {
2248 commandLine "mkdir", "-p", toDir
2251 commandLine "rsync", "-avh", "--delete", fromDir, toDir
2259 task getdownArchiveBuild() {
2260 group = "distribution"
2261 description = "Put files in the archive dir to go on the website"
2263 dependsOn getdownWebsite
2265 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
2266 def vDir = "${getdownArchiveDir}/${v}"
2267 getdownFullArchiveDir = "${vDir}/getdown"
2268 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
2270 def vAltDir = "alt_${v}"
2271 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
2274 // cleanup old "old" dir
2275 delete getdownArchiveDir
2277 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
2278 getdownArchiveTxt.getParentFile().mkdirs()
2279 def getdownArchiveTextLines = []
2280 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
2284 from "${getdownAppBaseDir}/${getdownAppDistDir}"
2285 into "${getdownFullArchiveDir}/${vAltDir}"
2288 getdownTextLines.each { line ->
2289 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
2290 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
2291 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
2292 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
2293 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
2294 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
2295 // remove the existing resource = resource/ or bin/ lines
2296 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
2297 getdownArchiveTextLines += line
2301 // the resource dir -- add these files as resource lines in getdown.txt
2303 from "${archiveImagesDir}"
2304 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
2306 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
2310 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
2312 def vLaunchJvl = file(getdownVersionLaunchJvl)
2313 vLaunchJvl.getParentFile().mkdirs()
2314 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
2315 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
2316 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
2317 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
2318 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
2319 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
2321 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2323 from getdownLauncher
2324 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
2325 from "${getdownAppBaseDir}/${getdown_launcher_new}"
2326 from "${getdownAppBaseDir}/${channel_props}"
2327 if (file(getdownLauncher).getName() != getdown_launcher) {
2328 rename(file(getdownLauncher).getName(), getdown_launcher)
2330 into getdownFullArchiveDir
2336 task getdownArchiveDigest(type: JavaExec) {
2337 group = "distribution"
2338 description = "Digest the getdown archive folder"
2340 dependsOn getdownArchiveBuild
2343 classpath = files(getdownLauncher)
2344 args getdownFullArchiveDir
2346 main = "com.threerings.getdown.tools.Digester"
2347 inputs.dir(getdownFullArchiveDir)
2348 outputs.file("${getdownFullArchiveDir}/digest2.txt")
2351 task getdownArchive() {
2352 group = "distribution"
2353 description = "Build the website archive dir with getdown digest"
2355 dependsOn getdownArchiveBuild
2356 dependsOn getdownArchiveDigest
2359 tasks.withType(JavaCompile) {
2360 options.encoding = 'UTF-8'
2366 delete getdownAppBaseDir
2367 delete getdownFilesDir
2368 delete getdownArchiveDir
2374 if (file(install4jHomeDir).exists()) {
2376 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
2377 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
2378 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
2379 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
2381 installDir(file(install4jHomeDir))
2383 mediaTypes = Arrays.asList(install4j_media_types.split(","))
2387 task copyInstall4jTemplate {
2388 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
2389 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
2390 inputs.file(install4jTemplateFile)
2391 inputs.file(install4jFileAssociationsFile)
2392 inputs.property("CHANNEL", { CHANNEL })
2393 outputs.file(install4jConfFile)
2396 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
2398 // turn off code signing if no OSX_KEYPASS
2399 if (OSX_KEYPASS == "") {
2400 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
2401 codeSigning.'@macEnabled' = "false"
2403 install4jConfigXml.'**'.windows.each { windows ->
2404 windows.'@runPostProcessor' = "false"
2408 // disable install screen for OSX dmg (for 2.11.2.0)
2409 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
2410 macosArchive.attributes().remove('executeSetupApp')
2411 macosArchive.attributes().remove('setupAppId')
2414 // turn off checksum creation for LOCAL channel
2415 def e = install4jConfigXml.application[0]
2416 e.'@createChecksums' = string(install4jCheckSums)
2418 // put file association actions where placeholder action is
2419 def install4jFileAssociationsText = install4jFileAssociationsFile.text
2420 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
2421 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
2422 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
2423 def parent = a.parent()
2425 fileAssociationActions.each { faa ->
2428 // don't need to continue in .any loop once replacements have been made
2433 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
2434 // NB we're deleting the /other/ one!
2435 // Also remove the examples subdir from non-release versions
2436 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
2437 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
2438 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
2439 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
2441 // remove the examples subdir from Full File Set
2442 def files = install4jConfigXml.files[0]
2443 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
2444 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
2445 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
2446 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
2447 dirEntry.parent().remove(dirEntry)
2449 install4jConfigXml.'**'.action.any { a ->
2450 if (a.'@customizedId' == customizedIdToDelete) {
2451 def parent = a.parent()
2457 // write install4j file
2458 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2465 delete install4jConfFile
2469 task cleanInstallersDataFiles {
2470 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2471 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2472 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2474 delete installersOutputTxt
2475 delete installersSha256
2476 delete hugoDataJsonFile
2480 task install4jDMGBackgroundImageCopy {
2481 inputs.file "${install4jDMGBackgroundImageDir}/${install4jDMGBackgroundImageFile}"
2482 outputs.dir "${install4jDMGBackgroundImageBuildDir}"
2485 from(install4jDMGBackgroundImageDir) {
2486 include(install4jDMGBackgroundImageFile)
2488 into install4jDMGBackgroundImageBuildDir
2493 task install4jDMGBackgroundImageProcess {
2494 dependsOn install4jDMGBackgroundImageCopy
2497 if (backgroundImageText) {
2498 if (convertBinary == null) {
2499 throw new StopExecutionException("No ImageMagick convert binary installed at '${convertBinaryExpectedLocation}'")
2501 if (!project.hasProperty("install4j_background_image_text_suffix_cmd")) {
2502 throw new StopExecutionException("No property 'install4j_background_image_text_suffix_cmd' defined. See channel_gradle.properties for channel ${CHANNEL}")
2504 fileTree(dir: install4jDMGBackgroundImageBuildDir, include: "*.png").getFiles().each { file ->
2506 executable convertBinary
2509 '-font', install4j_background_image_text_font,
2510 '-fill', install4j_background_image_text_colour,
2511 '-draw', sprintf(install4j_background_image_text_suffix_cmd, channelSuffix),
2512 '-draw', sprintf(install4j_background_image_text_commit_cmd, "git-commit: ${gitHash}"),
2513 '-draw', sprintf(install4j_background_image_text_date_cmd, getDate("yyyy-MM-dd HH:mm:ss")),
2522 task install4jDMGBackgroundImage {
2523 dependsOn install4jDMGBackgroundImageProcess
2526 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2527 group = "distribution"
2528 description = "Create the install4j installers"
2530 dependsOn copyInstall4jTemplate
2531 dependsOn cleanInstallersDataFiles
2532 dependsOn install4jDMGBackgroundImage
2534 projectFile = install4jConfFile
2536 // create an md5 for the input files to use as version for install4j conf file
2537 def digest = MessageDigest.getInstance("MD5")
2539 (file("${install4jDir}/${install4j_template}").text +
2540 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2541 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2542 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2543 if (filesMd5.length() >= 8) {
2544 filesMd5 = filesMd5.substring(0,8)
2546 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2549 'JALVIEW_NAME': jalview_name,
2550 'JALVIEW_APPLICATION_NAME': applicationName,
2551 'JALVIEW_DIR': "../..",
2552 'OSX_KEYSTORE': OSX_KEYSTORE,
2553 'OSX_APPLEID': OSX_APPLEID,
2554 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2555 'JSIGN_SH': JSIGN_SH,
2556 'JRE_DIR': getdown_app_dir_java,
2557 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2558 'JALVIEW_VERSION': JALVIEW_VERSION,
2559 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2560 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2561 'JAVA_VERSION': JAVA_VERSION,
2562 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2563 'VERSION': JALVIEW_VERSION,
2564 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2565 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2566 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2567 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2568 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2569 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2570 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2571 'BUNDLE_ID': install4jBundleId,
2572 'INTERNAL_ID': install4jInternalId,
2573 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2574 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2575 'MACOS_DMG_BG_IMAGE': "${install4jDMGBackgroundImageBuildDir}/${install4jDMGBackgroundImageFile}",
2576 'WRAPPER_LINK': getdownWrapperLink,
2577 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2578 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2579 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2580 'INSTALLER_NAME': install4jInstallerName,
2581 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2582 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2583 'GETDOWN_FILES_DIR': getdown_files_dir,
2584 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2585 'GETDOWN_DIST_DIR': getdownAppDistDir,
2586 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2587 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2588 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2589 'BUILD_DIR': install4jBuildDir,
2590 'APPLICATION_CATEGORIES': install4j_application_categories,
2591 'APPLICATION_FOLDER': install4jApplicationFolder,
2592 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2593 'EXECUTABLE_NAME': install4jExecutableName,
2594 'EXTRA_SCHEME': install4jExtraScheme,
2595 'MAC_ICONS_FILE': install4jMacIconsFile,
2596 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2597 'PNG_ICON_FILE': install4jPngIconFile,
2598 'BACKGROUND': install4jBackground,
2602 //println("INSTALL4J VARIABLES:")
2603 //variables.each{k,v->println("${k}=${v}")}
2605 destination = "${jalviewDir}/${install4jBuildDir}"
2606 buildSelected = true
2608 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2610 disableSigning = true
2611 disableNotarization = true
2615 macKeystorePassword = OSX_KEYPASS
2618 if (OSX_ALTOOLPASS) {
2619 appleIdPassword = OSX_ALTOOLPASS
2620 disableNotarization = false
2622 disableNotarization = true
2626 println("Using projectFile "+projectFile)
2627 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2631 inputs.dir(getdownAppBaseDir)
2632 inputs.file(install4jConfFile)
2633 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2634 inputs.dir(macosJavaVMDir)
2635 inputs.dir(windowsJavaVMDir)
2636 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2639 def getDataHash(File myFile) {
2640 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2641 return myFile.exists()
2643 "file" : myFile.getName(),
2644 "filesize" : myFile.length(),
2645 "sha256" : hash.toString()
2650 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2652 "channel" : getdownChannelName,
2653 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2654 "git-commit" : "${gitHash} [${gitBranch}]",
2655 "version" : JALVIEW_VERSION
2657 // install4j installer files
2658 if (installersOutputTxt.exists()) {
2660 installersOutputTxt.readLines().each { def line ->
2661 if (line.startsWith("#")) {
2664 line.replaceAll("\n","")
2665 def vals = line.split("\t")
2666 def filename = vals[3]
2667 def filesize = file(filename).length()
2668 filename = filename.replaceAll(/^.*\//, "")
2669 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2670 idHash."${filename}" = vals[0]
2672 if (install4jCheckSums && installersSha256.exists()) {
2673 installersSha256.readLines().each { def line ->
2674 if (line.startsWith("#")) {
2677 line.replaceAll("\n","")
2678 def vals = line.split(/\s+\*?/)
2679 def filename = vals[1]
2680 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2686 "JAR": shadowJar.archiveFile, // executable JAR
2687 "JVL": getdownVersionLaunchJvl, // version JVL
2688 "SOURCE": sourceDist.archiveFile // source TGZ
2689 ].each { key, value ->
2690 def file = file(value)
2691 if (file.exists()) {
2692 def fileHash = getDataHash(file)
2693 if (fileHash != null) {
2694 hash."${key}" = fileHash;
2698 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2701 task staticMakeInstallersJsonFile {
2703 def output = findProperty("i4j_output")
2704 def sha256 = findProperty("i4j_sha256")
2705 def json = findProperty("i4j_json")
2706 if (output == null || sha256 == null || json == null) {
2707 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2709 writeDataJsonFile(file(output), file(sha256), file(json))
2714 dependsOn installerFiles
2720 eclipse().configFile(eclipse_codestyle_file)
2724 task createSourceReleaseProperties(type: WriteProperties) {
2725 group = "distribution"
2726 description = "Create the source RELEASE properties file"
2728 def sourceTarBuildDir = "${buildDir}/sourceTar"
2729 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2730 outputFile (sourceReleasePropertiesFile)
2733 releaseProps.each{ key, val -> property key, val }
2734 property "git.branch", gitBranch
2735 property "git.hash", gitHash
2738 outputs.file(outputFile)
2741 task sourceDist(type: Tar) {
2742 group "distribution"
2743 description "Create a source .tar.gz file for distribution"
2745 dependsOn createBuildProperties
2746 dependsOn convertMdFiles
2747 dependsOn eclipseAllPreferences
2748 dependsOn createSourceReleaseProperties
2751 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2752 archiveFileName = outputFileName
2754 compression Compression.GZIP
2769 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2771 "utils/InstallAnywhere",
2786 "gradle.properties",
2798 ".settings/org.eclipse.buildship.core.prefs",
2799 ".settings/org.eclipse.jdt.core.prefs"
2803 exclude (EXCLUDE_FILES)
2804 include (PROCESS_FILES)
2805 filter(ReplaceTokens,
2809 'Version-Rel': JALVIEW_VERSION,
2810 'Year-Rel': getDate("yyyy")
2815 exclude (EXCLUDE_FILES)
2816 exclude (PROCESS_FILES)
2817 exclude ("appletlib")
2818 exclude ("**/*locales")
2819 exclude ("*locales/**")
2820 exclude ("utils/InstallAnywhere")
2822 exclude (getdown_files_dir)
2823 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2824 //exclude (getdown_website_dir)
2825 //exclude (getdown_archive_dir)
2827 // exluding these as not using jars as modules yet
2828 exclude ("${j11modDir}/**/*.jar")
2831 include(INCLUDE_FILES)
2833 // from (jalviewDir) {
2834 // // explicit includes for stuff that seemed to not get included
2835 // include(fileTree("test/**/*."))
2836 // exclude(EXCLUDE_FILES)
2837 // exclude(PROCESS_FILES)
2840 from(file(buildProperties).getParent()) {
2841 include(file(buildProperties).getName())
2842 rename(file(buildProperties).getName(), "build_properties")
2844 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2848 def sourceTarBuildDir = "${buildDir}/sourceTar"
2849 from(sourceTarBuildDir) {
2850 // this includes the appended RELEASE properties file
2854 task dataInstallersJson {
2856 description "Create the installers-VERSION.json data file for installer files created"
2858 mustRunAfter installers
2859 mustRunAfter shadowJar
2860 mustRunAfter sourceDist
2861 mustRunAfter getdownArchive
2863 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2864 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2866 if (installersOutputTxt.exists()) {
2867 inputs.file(installersOutputTxt)
2869 if (install4jCheckSums && installersSha256.exists()) {
2870 inputs.file(installersSha256)
2873 shadowJar.archiveFile, // executable JAR
2874 getdownVersionLaunchJvl, // version JVL
2875 sourceDist.archiveFile // source TGZ
2876 ].each { fileName ->
2877 if (file(fileName).exists()) {
2878 inputs.file(fileName)
2882 outputs.file(hugoDataJsonFile)
2885 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2891 description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'."
2894 dependsOn pubhtmlhelp
2896 inputs.dir("${helpBuildDir}/${help_dir}")
2897 outputs.dir("${buildDir}/distributions/${help_dir}")
2901 task j2sSetHeadlessBuild {
2908 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2910 description "Enable the alternative J2S Config file for headless build"
2912 outputFile = jalviewjsJ2sSettingsFileName
2913 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2914 def j2sProps = new Properties()
2915 if (j2sPropsFile.exists()) {
2917 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2918 j2sProps.load(j2sPropsFileFIS)
2919 j2sPropsFileFIS.close()
2921 j2sProps.each { prop, val ->
2924 } catch (Exception e) {
2925 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2929 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2930 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2935 task jalviewjsSetEclipseWorkspace {
2936 def propKey = "jalviewjs_eclipse_workspace"
2938 if (project.hasProperty(propKey)) {
2939 propVal = project.getProperty(propKey)
2940 if (propVal.startsWith("~/")) {
2941 propVal = System.getProperty("user.home") + propVal.substring(1)
2944 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2945 def propsFile = file(propsFileName)
2946 def eclipseWsDir = propVal
2947 def props = new Properties()
2949 def writeProps = true
2950 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2951 def ins = new FileInputStream(propsFileName)
2954 if (props.getProperty(propKey, null) != null) {
2955 eclipseWsDir = props.getProperty(propKey)
2960 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2961 def tempDir = File.createTempDir()
2962 eclipseWsDir = tempDir.getAbsolutePath()
2965 eclipseWorkspace = file(eclipseWsDir)
2968 // do not run a headless transpile when we claim to be in Eclipse
2970 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2971 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2973 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2977 props.setProperty(propKey, eclipseWsDir)
2978 propsFile.parentFile.mkdirs()
2979 def bytes = new ByteArrayOutputStream()
2980 props.store(bytes, null)
2981 def propertiesString = bytes.toString()
2982 propsFile.text = propertiesString
2988 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2991 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2992 outputs.file(propsFileName)
2993 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2997 task jalviewjsEclipsePaths {
3000 def eclipseRoot = jalviewjs_eclipse_root
3001 if (eclipseRoot.startsWith("~/")) {
3002 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
3004 if (OperatingSystem.current().isMacOsX()) {
3005 eclipseRoot += "/Eclipse.app"
3006 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
3007 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
3008 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
3009 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
3010 eclipseRoot += "/eclipse"
3012 eclipseBinary = "${eclipseRoot}/eclipse.exe"
3013 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
3014 } else { // linux or unix
3015 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
3016 eclipseRoot += "/eclipse"
3017 println("eclipseDir exists")
3019 eclipseBinary = "${eclipseRoot}/eclipse"
3020 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
3023 eclipseVersion = "4.13" // default
3024 def assumedVersion = true
3025 if (file(eclipseProduct).exists()) {
3026 def fis = new FileInputStream(eclipseProduct)
3027 def props = new Properties()
3029 eclipseVersion = props.getProperty("version")
3031 assumedVersion = false
3034 def propKey = "eclipse_debug"
3035 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
3038 // do not run a headless transpile when we claim to be in Eclipse
3040 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3041 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3043 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3046 if (!assumedVersion) {
3047 println("ECLIPSE VERSION=${eclipseVersion}")
3053 task printProperties {
3055 description "Output to console all System.properties"
3057 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
3063 dependsOn eclipseProject
3064 dependsOn eclipseClasspath
3065 dependsOn eclipseJdt
3069 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
3070 task jalviewjsEclipseCopyDropins(type: Copy) {
3071 dependsOn jalviewjsEclipsePaths
3073 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
3074 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
3075 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
3082 // this eclipse -clean doesn't actually work
3083 task jalviewjsCleanEclipse(type: Exec) {
3084 dependsOn eclipseSetup
3085 dependsOn jalviewjsEclipsePaths
3086 dependsOn jalviewjsEclipseCopyDropins
3088 executable(eclipseBinary)
3089 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
3095 def inputString = """exit
3098 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
3099 standardInput = inputByteStream
3102 /* not really working yet
3103 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
3107 task jalviewjsTransferUnzipSwingJs {
3108 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
3112 from zipTree(file_zip)
3113 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3117 inputs.file file_zip
3118 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3122 task jalviewjsTransferUnzipLib {
3123 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
3126 zipFiles.each { file_zip ->
3128 from zipTree(file_zip)
3129 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3134 inputs.files zipFiles
3135 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3139 task jalviewjsTransferUnzipAllLibs {
3140 dependsOn jalviewjsTransferUnzipSwingJs
3141 dependsOn jalviewjsTransferUnzipLib
3145 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
3147 description "Create the alternative j2s file from the j2s.* properties"
3149 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
3150 def siteDirProperty = "j2s.site.directory"
3151 def setSiteDir = false
3152 jalviewjsJ2sProps.each { prop, val ->
3154 if (prop == siteDirProperty) {
3155 if (!(val.startsWith('/') || val.startsWith("file://") )) {
3156 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3162 if (!setSiteDir) { // default site location, don't override specifically set property
3163 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3166 outputFile = jalviewjsJ2sAltSettingsFileName
3169 inputs.properties(jalviewjsJ2sProps)
3170 outputs.file(jalviewjsJ2sAltSettingsFileName)
3175 task jalviewjsEclipseSetup {
3176 dependsOn jalviewjsEclipseCopyDropins
3177 dependsOn jalviewjsSetEclipseWorkspace
3178 dependsOn jalviewjsCreateJ2sSettings
3182 task jalviewjsSyncAllLibs (type: Sync) {
3183 dependsOn jalviewjsTransferUnzipAllLibs
3184 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3185 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3186 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3190 def outputFiles = []
3191 rename { filename ->
3192 outputFiles += "${outputDir}/${filename}"
3199 // should this be exclude really ?
3200 duplicatesStrategy "INCLUDE"
3202 outputs.files outputFiles
3203 inputs.files inputFiles
3207 task jalviewjsSyncResources (type: Sync) {
3208 dependsOn buildResources
3210 def inputFiles = fileTree(dir: resourcesBuildDir)
3211 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3215 def outputFiles = []
3216 rename { filename ->
3217 outputFiles += "${outputDir}/${filename}"
3223 outputs.files outputFiles
3224 inputs.files inputFiles
3228 task jalviewjsSyncSiteResources (type: Sync) {
3229 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3230 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3234 def outputFiles = []
3235 rename { filename ->
3236 outputFiles += "${outputDir}/${filename}"
3242 outputs.files outputFiles
3243 inputs.files inputFiles
3247 task jalviewjsSyncBuildProperties (type: Sync) {
3248 dependsOn createBuildProperties
3249 def inputFiles = [file(buildProperties)]
3250 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3254 def outputFiles = []
3255 rename { filename ->
3256 outputFiles += "${outputDir}/${filename}"
3262 outputs.files outputFiles
3263 inputs.files inputFiles
3267 task jalviewjsProjectImport(type: Exec) {
3268 dependsOn eclipseSetup
3269 dependsOn jalviewjsEclipsePaths
3270 dependsOn jalviewjsEclipseSetup
3273 // do not run a headless import when we claim to be in Eclipse
3275 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3276 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3278 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3282 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3283 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3284 executable(eclipseBinary)
3285 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3289 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3291 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3292 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3295 inputs.file("${jalviewDir}/.project")
3296 outputs.upToDateWhen {
3297 file(projdir).exists()
3302 task jalviewjsTranspile(type: Exec) {
3303 dependsOn jalviewjsEclipseSetup
3304 dependsOn jalviewjsProjectImport
3305 dependsOn jalviewjsEclipsePaths
3307 dependsOn jalviewjsEnableAltFileProperty
3311 // do not run a headless transpile when we claim to be in Eclipse
3313 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3314 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3316 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3320 executable(eclipseBinary)
3321 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3325 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3327 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3328 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3334 stdout = new ByteArrayOutputStream()
3335 stderr = new ByteArrayOutputStream()
3337 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3338 def logOutFile = file(logOutFileName)
3339 logOutFile.createNewFile()
3340 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3341 BINARY: ${eclipseBinary}
3342 VERSION: ${eclipseVersion}
3343 WORKSPACE: ${eclipseWorkspace}
3344 DEBUG: ${eclipseDebug}
3347 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3348 // combine stdout and stderr
3349 def logErrFOS = logOutFOS
3351 if (jalviewjs_j2s_to_console.equals("true")) {
3352 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3353 new org.apache.tools.ant.util.TeeOutputStream(
3357 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3358 new org.apache.tools.ant.util.TeeOutputStream(
3363 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3366 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3373 if (stdout.toString().contains("Error processing ")) {
3374 // j2s did not complete transpile
3375 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3376 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3377 println("IGNORING TRANSPILE ERRORS")
3378 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3380 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3385 inputs.dir("${jalviewDir}/${sourceDir}")
3386 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3387 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3391 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3393 def stdout = new ByteArrayOutputStream()
3394 def stderr = new ByteArrayOutputStream()
3396 def coreFile = file(jsfile)
3398 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3400 logOutFile.createNewFile()
3401 logOutFile.append(msg+"\n")
3403 def coreTop = file(prefixFile)
3404 def coreBottom = file(suffixFile)
3405 coreFile.getParentFile().mkdirs()
3406 coreFile.createNewFile()
3407 coreFile.write( coreTop.getText("UTF-8") )
3411 def t = f.getText("UTF-8")
3412 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3413 coreFile.append( t )
3415 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3417 logOutFile.append(msg+"\n")
3420 coreFile.append( coreBottom.getText("UTF-8") )
3422 msg = "Generating ${zjsfile}"
3424 logOutFile.append(msg+"\n")
3425 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3426 def logErrFOS = logOutFOS
3429 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3430 main = "com.google.javascript.jscomp.CommandLineRunner"
3431 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3432 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3435 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3437 logOutFile.append(msg+"\n")
3439 if (logOutConsole) {
3440 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3441 new org.apache.tools.ant.util.TeeOutputStream(
3445 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3446 new org.apache.tools.ant.util.TeeOutputStream(
3451 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3454 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3461 logOutFile.append(msg+"\n")
3465 task jalviewjsBuildAllCores {
3467 description "Build the core js lib closures listed in the classlists dir"
3468 dependsOn jalviewjsTranspile
3469 dependsOn jalviewjsTransferUnzipSwingJs
3471 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3472 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3473 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3474 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3475 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3476 def prefixFile = "${jsDir}/core/coretop2.js"
3477 def suffixFile = "${jsDir}/core/corebottom2.js"
3479 inputs.file prefixFile
3480 inputs.file suffixFile
3482 def classlistFiles = []
3483 // add the classlists found int the jalviewjs_classlists_dir
3484 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3486 def name = file.getName() - ".txt"
3493 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3494 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3495 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3497 jalviewjsCoreClasslists = []
3499 classlistFiles.each {
3502 def file = hash['file']
3503 if (! file.exists()) {
3504 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3505 return false // this is a "continue" in groovy .each closure
3507 def name = hash['name']
3509 name = file.getName() - ".txt"
3517 def list = fileTree(dir: j2sDir, includes: filelist)
3519 def jsfile = "${outputDir}/core${name}.js"
3520 def zjsfile = "${outputDir}/core${name}.z.js"
3522 jalviewjsCoreClasslists += [
3531 outputs.file(jsfile)
3532 outputs.file(zjsfile)
3535 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3536 def stevesoftClasslistName = "_stevesoft"
3537 def stevesoftClasslist = [
3538 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3539 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3540 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3541 'name': stevesoftClasslistName
3543 jalviewjsCoreClasslists += stevesoftClasslist
3544 inputs.files(stevesoftClasslist['list'])
3545 outputs.file(stevesoftClasslist['jsfile'])
3546 outputs.file(stevesoftClasslist['zjsfile'])
3549 def allClasslistName = "_all"
3550 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3551 allJsFiles += fileTree(
3555 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3556 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3557 "**/org/jmol/export/JSExporter.js"
3560 allJsFiles += fileTree(
3564 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3565 "**/sun/misc/Unsafe.js",
3566 "**/swingjs/jquery/jquery-editable-select.js",
3567 "**/swingjs/jquery/j2sComboBox.js",
3568 "**/sun/misc/FloatingDecimal.js"
3571 def allClasslist = [
3572 'jsfile': "${outputDir}/core${allClasslistName}.js",
3573 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3575 'name': allClasslistName
3577 // not including this version of "all" core at the moment
3578 //jalviewjsCoreClasslists += allClasslist
3579 inputs.files(allClasslist['list'])
3580 outputs.file(allClasslist['jsfile'])
3581 outputs.file(allClasslist['zjsfile'])
3584 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3585 logOutFile.getParentFile().mkdirs()
3586 logOutFile.createNewFile()
3587 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3589 jalviewjsCoreClasslists.each {
3590 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3597 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3600 into file(outputFile).getParentFile()
3601 rename { filename ->
3602 if (filename.equals(inputFile.getName())) {
3603 return file(outputFile).getName()
3607 filter(ReplaceTokens,
3611 'MAIN': '"'+main_class+'"',
3613 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3614 'COREKEY': jalviewjs_core_key,
3615 'CORENAME': coreName
3622 task jalviewjsPublishCoreTemplates {
3623 dependsOn jalviewjsBuildAllCores
3624 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3625 def inputFile = file(inputFileName)
3626 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3628 def outputFiles = []
3629 jalviewjsCoreClasslists.each { cl ->
3630 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3631 cl['outputfile'] = outputFile
3632 outputFiles += outputFile
3636 jalviewjsCoreClasslists.each { cl ->
3637 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3640 inputs.file(inputFile)
3641 outputs.files(outputFiles)
3645 task jalviewjsSyncCore (type: Sync) {
3646 dependsOn jalviewjsBuildAllCores
3647 dependsOn jalviewjsPublishCoreTemplates
3648 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3649 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3653 def outputFiles = []
3654 rename { filename ->
3655 outputFiles += "${outputDir}/${filename}"
3661 outputs.files outputFiles
3662 inputs.files inputFiles
3666 // this Copy version of TransferSiteJs will delete anything else in the target dir
3667 task jalviewjsCopyTransferSiteJs(type: Copy) {
3668 dependsOn jalviewjsTranspile
3669 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3670 into "${jalviewDir}/${jalviewjsSiteDir}"
3674 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3675 task jalviewjsSyncTransferSiteJs(type: Sync) {
3676 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3678 into "${jalviewDir}/${jalviewjsSiteDir}"
3685 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3686 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3687 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3688 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3690 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3691 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3692 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3693 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3696 task jalviewjsPrepareSite {
3698 description "Prepares the website folder including unzipping files and copying resources"
3699 dependsOn jalviewjsSyncAllLibs
3700 dependsOn jalviewjsSyncResources
3701 dependsOn jalviewjsSyncSiteResources
3702 dependsOn jalviewjsSyncBuildProperties
3703 dependsOn jalviewjsSyncCore
3707 task jalviewjsBuildSite {
3709 description "Builds the whole website including transpiled code"
3710 dependsOn jalviewjsCopyTransferSiteJs
3711 dependsOn jalviewjsPrepareSite
3715 task cleanJalviewjsTransferSite {
3717 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3718 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3719 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3720 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3725 task cleanJalviewjsSite {
3726 dependsOn cleanJalviewjsTransferSite
3728 delete "${jalviewDir}/${jalviewjsSiteDir}"
3733 task jalviewjsSiteTar(type: Tar) {
3735 description "Creates a tar.gz file for the website"
3736 dependsOn jalviewjsBuildSite
3737 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3738 archiveFileName = outputFilename
3740 compression Compression.GZIP
3742 from "${jalviewDir}/${jalviewjsSiteDir}"
3743 into jalviewjs_site_dir // this is inside the tar file
3745 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3749 task jalviewjsServer {
3751 def filename = "jalviewjsTest.html"
3752 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3753 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3758 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3759 factory = f.newInstance()
3760 } catch (ClassNotFoundException e) {
3761 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3763 def port = Integer.valueOf(jalviewjs_server_port)
3768 while(port < start+1000 && !running) {
3770 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3771 jalviewjsServer = factory.start(doc_root, port)
3773 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3774 println("SERVER STARTED with document root ${doc_root}.")
3775 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3776 println("For debug: "+url+"?j2sdebug")
3777 println("For verbose: "+url+"?j2sverbose")
3778 } catch (Exception e) {
3783 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3784 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3785 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3787 jalviewjsCoreClasslists.each { cl ->
3788 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3790 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3792 println("For core ${cl.name}: "+urlcore)
3795 file(htmlFile).text = htmlText
3798 outputs.file(htmlFile)
3799 outputs.upToDateWhen({false})
3803 task cleanJalviewjsAll {
3805 description "Delete all configuration and build artifacts to do with JalviewJS build"
3806 dependsOn cleanJalviewjsSite
3807 dependsOn jalviewjsEclipsePaths
3810 delete "${jalviewDir}/${jalviewjsBuildDir}"
3811 delete "${jalviewDir}/${eclipse_bin_dir}"
3812 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3813 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3815 delete jalviewjsJ2sAltSettingsFileName
3818 outputs.upToDateWhen( { false } )
3822 task jalviewjsIDE_checkJ2sPlugin {
3823 group "00 JalviewJS in Eclipse"
3824 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3827 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3828 def j2sPluginFile = file(j2sPlugin)
3829 def eclipseHome = System.properties["eclipse.home.location"]
3830 if (eclipseHome == null || ! IN_ECLIPSE) {
3831 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3833 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3834 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3835 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3836 eclipseJ2sPluginDirs += altPluginsDir
3838 def foundPlugin = false
3839 def j2sPluginFileName = j2sPluginFile.getName()
3840 def eclipseJ2sPlugin
3841 def eclipseJ2sPluginFile
3842 eclipseJ2sPluginDirs.any { dir ->
3843 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3844 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3845 if (eclipseJ2sPluginFile.exists()) {
3851 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3852 System.err.println(msg)
3853 throw new StopExecutionException(msg)
3856 def digest = MessageDigest.getInstance("MD5")
3858 digest.update(j2sPluginFile.text.bytes)
3859 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3861 digest.update(eclipseJ2sPluginFile.text.bytes)
3862 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3864 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3865 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3866 System.err.println(msg)
3867 throw new StopExecutionException(msg)
3869 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3875 task jalviewjsIDE_copyJ2sPlugin {
3876 group "00 JalviewJS in Eclipse"
3877 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3880 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3881 def j2sPluginFile = file(j2sPlugin)
3882 def eclipseHome = System.properties["eclipse.home.location"]
3883 if (eclipseHome == null || ! IN_ECLIPSE) {
3884 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3886 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3887 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3888 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3889 System.err.println(msg)
3892 eclipseJ2sPluginFile.getParentFile().mkdirs()
3893 into eclipseJ2sPluginFile.getParent()
3899 task jalviewjsIDE_j2sFile {
3900 group "00 JalviewJS in Eclipse"
3901 description "Creates the .j2s file"
3902 dependsOn jalviewjsCreateJ2sSettings
3906 task jalviewjsIDE_SyncCore {
3907 group "00 JalviewJS in Eclipse"
3908 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3909 dependsOn jalviewjsSyncCore
3913 task jalviewjsIDE_SyncSiteAll {
3914 dependsOn jalviewjsSyncAllLibs
3915 dependsOn jalviewjsSyncResources
3916 dependsOn jalviewjsSyncSiteResources
3917 dependsOn jalviewjsSyncBuildProperties
3921 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3924 task jalviewjsIDE_PrepareSite {
3925 group "00 JalviewJS in Eclipse"
3926 description "Sync libs and resources to site dir, but not closure cores"
3928 dependsOn jalviewjsIDE_SyncSiteAll
3929 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3933 task jalviewjsIDE_AssembleSite {
3934 group "00 JalviewJS in Eclipse"
3935 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3936 dependsOn jalviewjsPrepareSite
3940 task jalviewjsIDE_SiteClean {
3941 group "00 JalviewJS in Eclipse"
3942 description "Deletes the Eclipse transpiled site"
3943 dependsOn cleanJalviewjsSite
3947 task jalviewjsIDE_Server {
3948 group "00 JalviewJS in Eclipse"
3949 description "Starts a webserver on localhost to test the website"
3950 dependsOn jalviewjsServer
3954 // buildship runs this at import or gradle refresh
3955 task eclipseSynchronizationTask {
3956 //dependsOn eclipseSetup
3957 dependsOn createBuildProperties
3959 dependsOn jalviewjsIDE_j2sFile
3960 dependsOn jalviewjsIDE_checkJ2sPlugin
3961 dependsOn jalviewjsIDE_PrepareSite
3966 // buildship runs this at build time or project refresh
3967 task eclipseAutoBuildTask {
3968 //dependsOn jalviewjsIDE_checkJ2sPlugin
3969 //dependsOn jalviewjsIDE_PrepareSite
3975 description "Build the site"
3976 dependsOn jalviewjsBuildSite