1 /* Convention for properties. Read from gradle.properties, use lower_case_underlines for property names.
2 * For properties set within build.gradle, use camelCaseNoSpace.
4 import org.apache.tools.ant.filters.ReplaceTokens
5 import org.gradle.internal.os.OperatingSystem
6 import org.gradle.plugins.ide.internal.generator.PropertiesPersistableConfigurationObject
7 import org.gradle.api.internal.PropertiesTransformer
8 import org.gradle.util.ConfigureUtil
9 import org.gradle.plugins.ide.eclipse.model.Output
10 import org.gradle.plugins.ide.eclipse.model.Library
11 import java.security.MessageDigest
12 import java.util.regex.Matcher
13 import groovy.transform.ExternalizeMethods
14 import groovy.util.XmlParser
15 import groovy.xml.XmlUtil
16 import groovy.json.JsonBuilder
17 import com.vladsch.flexmark.util.ast.Node
18 import com.vladsch.flexmark.html.HtmlRenderer
19 import com.vladsch.flexmark.parser.Parser
20 import com.vladsch.flexmark.util.data.MutableDataSet
21 import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension
22 import com.vladsch.flexmark.ext.tables.TablesExtension
23 import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension
24 import com.vladsch.flexmark.ext.autolink.AutolinkExtension
25 import com.vladsch.flexmark.ext.anchorlink.AnchorLinkExtension
26 import com.vladsch.flexmark.ext.toc.TocExtension
27 import com.google.common.hash.HashCode
28 import com.google.common.hash.Hashing
29 import com.google.common.io.Files
30 import org.jsoup.Jsoup
31 import org.jsoup.nodes.Element
39 classpath "com.vladsch.flexmark:flexmark-all:0.62.0"
40 classpath "org.jsoup:jsoup:1.14.3"
41 classpath "com.eowise:gradle-imagemagick:0.5.1"
50 id "com.diffplug.gradle.spotless" version "3.28.0"
51 id 'com.github.johnrengelman.shadow' version '4.0.3'
52 id 'com.install4j.gradle' version '9.0.6'
53 id 'com.dorongold.task-tree' version '2.1.0' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
54 id 'com.palantir.git-version' version '0.13.0' apply false
65 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
66 def string(Object o) {
67 return o == null ? "" : o.toString()
70 def overrideProperties(String propsFileName, boolean output = false) {
71 if (propsFileName == null) {
74 def propsFile = file(propsFileName)
75 if (propsFile != null && propsFile.exists()) {
76 println("Using properties from file '${propsFileName}'")
78 def p = new Properties()
79 def localPropsFIS = new FileInputStream(propsFile)
85 if (project.hasProperty(key)) {
86 oldval = project.findProperty(key)
87 project.setProperty(key, val)
89 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
92 ext.setProperty(key, val)
94 println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'")
98 } catch (Exception e) {
99 println("Exception reading local.properties")
106 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
107 jalviewDirRelativePath = jalviewDir
110 getdownChannelName = CHANNEL.toLowerCase()
111 // default to "default". Currently only has different cosmetics for "develop", "release", "default"
112 propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default"
113 channelDirName = propertiesChannelName
114 // Import channel_properties
115 if (getdownChannelName.startsWith("develop-")) {
116 channelDirName = "develop-SUFFIX"
118 channelDir = string("${jalviewDir}/${channel_properties_dir}/${channelDirName}")
119 channelGradleProperties = string("${channelDir}/channel_gradle.properties")
120 channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}")
121 overrideProperties(channelGradleProperties, false)
122 // local build environment properties
123 // can be "projectDir/local.properties"
124 overrideProperties("${projectDir}/local.properties", true)
125 // or "../projectDir_local.properties"
126 overrideProperties(projectDir.getParent() + "/" + projectDir.getName() + "_local.properties", true)
129 // Import releaseProps from the RELEASE file
130 // or a file specified via JALVIEW_RELEASE_FILE if defined
131 // Expect jalview.version and target release branch in jalview.release
132 releaseProps = new Properties();
133 def releasePropFile = findProperty("JALVIEW_RELEASE_FILE");
134 def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE";
136 (new File(releasePropFile!=null ? releasePropFile : defaultReleasePropFile)).withInputStream {
137 releaseProps.load(it)
139 } catch (Exception fileLoadError) {
140 throw new Error("Couldn't load release properties file "+(releasePropFile==null ? defaultReleasePropFile : "from custom location: releasePropFile"),fileLoadError);
143 // Set JALVIEW_VERSION if it is not already set
144 if (findProperty("JALVIEW_VERSION")==null || "".equals(JALVIEW_VERSION)) {
145 JALVIEW_VERSION = releaseProps.get("jalview.version")
147 println("JALVIEW_VERSION is set to '${JALVIEW_VERSION}'")
149 // this property set when running Eclipse headlessly
150 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
151 // this property set by Eclipse
152 eclipseApplicationProperty = string("eclipse.application")
153 // CHECK IF RUNNING FROM WITHIN ECLIPSE
154 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
155 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
156 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
157 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
158 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
162 println("WITHIN ECLIPSE IDE")
164 println("HEADLESS BUILD")
167 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
169 println("J2S ENABLED")
172 System.properties.sort { it.key }.each {
173 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
176 if (false && IN_ECLIPSE) {
177 jalviewDir = jalviewDirAbsolutePath
182 buildDate = new Date().format("yyyyMMdd")
185 bareSourceDir = string(source_dir)
186 sourceDir = string("${jalviewDir}/${bareSourceDir}")
187 resourceDir = string("${jalviewDir}/${resource_dir}")
188 bareTestSourceDir = string(test_source_dir)
189 testDir = string("${jalviewDir}/${bareTestSourceDir}")
191 classesDir = string("${jalviewDir}/${classes_dir}")
194 useClover = clover.equals("true")
195 cloverBuildDir = "${buildDir}/clover"
196 cloverInstrDir = file("${cloverBuildDir}/clover-instr")
197 cloverClassesDir = file("${cloverBuildDir}/clover-classes")
198 cloverReportDir = file("${buildDir}/reports/clover")
199 cloverTestInstrDir = file("${cloverBuildDir}/clover-test-instr")
200 cloverTestClassesDir = file("${cloverBuildDir}/clover-test-classes")
201 //cloverTestClassesDir = cloverClassesDir
202 cloverDb = string("${cloverBuildDir}/clover.db")
204 testSourceDir = useClover ? cloverTestInstrDir : testDir
205 testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}"
208 backgroundImageText = BACKGROUNDIMAGETEXT
209 getdownChannelDir = string("${getdown_website_dir}/${propertiesChannelName}")
210 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
211 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
212 getdownFullArchiveDir = null
213 getdownTextLines = []
214 getdownLaunchJvl = null
215 getdownVersionLaunchJvl = null
217 buildProperties = null
219 // the following values might be overridden by the CHANNEL switch
220 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
221 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
222 getdownArchiveAppBase = getdown_archive_base
223 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
224 getdownAppDistDir = getdown_app_dir_alt
225 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
226 getdownImagesBuildDir = string("${buildDir}/imagemagick/getdown")
227 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
228 reportRsyncCommand = false
229 jvlChannelName = CHANNEL.toLowerCase()
230 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
231 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
232 install4jDMGBackgroundImageDir = "${install4j_images_dir}"
233 install4jDMGBackgroundImageBuildDir = "build/imagemagick/install4j"
234 install4jDMGBackgroundImageFile = "${install4j_dmg_background}"
235 install4jInstallerName = "${jalview_name} Non-Release Installer"
236 install4jExecutableName = install4j_executable_name
237 install4jExtraScheme = "jalviewx"
238 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
239 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
240 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
241 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
242 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
243 install4jCheckSums = true
245 applicationName = "${jalview_name}"
249 // TODO: get bamboo build artifact URL for getdown artifacts
250 getdown_channel_base = bamboo_channelbase
251 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
252 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
253 jvlChannelName += "_${getdownChannelName}"
254 // automatically add the test group Not-bamboo for exclusion
255 if ("".equals(testng_excluded_groups)) {
256 testng_excluded_groups = "Not-bamboo"
258 install4jExtraScheme = "jalviewb"
259 backgroundImageText = true
262 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
263 getdownAppDistDir = getdown_app_dir_release
264 getdownSetAppBaseProperty = true
265 reportRsyncCommand = true
267 install4jInstallerName = "${jalview_name} Installer"
271 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
272 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
273 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
274 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
275 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
277 package_dir = string("${ARCHIVEDIR}/${package_dir}")
278 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
281 reportRsyncCommand = true
282 install4jExtraScheme = "jalviewa"
286 getdownChannelName = string("archive/${JALVIEW_VERSION}")
287 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
288 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
289 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
290 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution [did not find '${ARCHIVEDIR}/${package_dir}']")
292 package_dir = string("${ARCHIVEDIR}/${package_dir}")
293 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
296 reportRsyncCommand = true
297 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
298 install4jSuffix = "Archive"
299 install4jExtraScheme = "jalviewa"
302 case ~/^DEVELOP-([\.\-\w]*)$/:
303 def suffix = Matcher.lastMatcher[0][1]
304 reportRsyncCommand = true
305 getdownSetAppBaseProperty = true
306 JALVIEW_VERSION=JALVIEW_VERSION+"-d${suffix}-${buildDate}"
307 install4jSuffix = "Develop ${suffix}"
308 install4jExtraScheme = "jalviewd"
309 install4jInstallerName = "${jalview_name} Develop ${suffix} Installer"
310 getdownChannelName = string("develop-${suffix}")
311 getdownChannelDir = string("${getdown_website_dir}/${getdownChannelName}")
312 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
313 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
314 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
315 channelSuffix = string(suffix)
316 backgroundImageText = true
320 reportRsyncCommand = true
321 getdownSetAppBaseProperty = true
322 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
323 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
325 install4jSuffix = "Develop"
326 install4jExtraScheme = "jalviewd"
327 install4jInstallerName = "${jalview_name} Develop Installer"
328 backgroundImageText = true
332 reportRsyncCommand = true
333 getdownSetAppBaseProperty = true
334 // Don't ignore transpile errors for release build
335 if (jalviewjs_ignore_transpile_errors.equals("true")) {
336 jalviewjs_ignore_transpile_errors = "false"
337 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
339 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
340 install4jSuffix = "Test"
341 install4jExtraScheme = "jalviewt"
342 install4jInstallerName = "${jalview_name} Test Installer"
343 backgroundImageText = true
346 case ~/^SCRATCH(|-[-\w]*)$/:
347 getdownChannelName = CHANNEL
348 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
350 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
351 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
352 reportRsyncCommand = true
353 install4jSuffix = "Scratch"
357 if (!file("${LOCALDIR}").exists()) {
358 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
360 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
361 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
363 JALVIEW_VERSION = "TEST"
364 install4jSuffix = "Test-Local"
365 install4jExtraScheme = "jalviewt"
366 install4jInstallerName = "${jalview_name} Test Installer"
367 backgroundImageText = true
370 case [ "LOCAL", "JALVIEWJS" ]:
371 JALVIEW_VERSION = "TEST"
372 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
373 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
374 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
375 install4jExtraScheme = "jalviewl"
376 install4jCheckSums = false
379 default: // something wrong specified
380 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
384 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
385 hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_data_installers_dir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
386 hugoArchiveMdFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_version_archive_dir}/Version-${JALVIEW_VERSION_UNDERSCORES}/_index.md")
387 // override getdownAppBase if requested
388 if (findProperty("getdown_appbase_override") != null) {
389 // revert to LOCAL if empty string
390 if (string(getdown_appbase_override) == "") {
391 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
392 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
393 } else if (string(getdown_appbase_override).startsWith("file://")) {
394 getdownAppBase = string(getdown_appbase_override)
395 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
397 getdownAppBase = string(getdown_appbase_override)
399 println("Overriding getdown appbase with '${getdownAppBase}'")
401 // sanitise file name for jalview launcher file for this channel
402 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
403 // install4j application and folder names
404 if (install4jSuffix == "") {
405 install4jBundleId = "${install4j_bundle_id}"
406 install4jWinApplicationId = install4j_release_win_application_id
408 applicationName = "${jalview_name} ${install4jSuffix}"
409 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
410 // add int hash of install4jSuffix to the last part of the application_id
411 def id = install4j_release_win_application_id
412 def idsplitreverse = id.split("-").reverse()
413 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
414 install4jWinApplicationId = idsplitreverse.reverse().join("-")
416 // sanitise folder and id names
417 // install4jApplicationFolder = e.g. "Jalview Build"
418 install4jApplicationFolder = applicationName
419 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
420 .replaceAll("_+", "_") // collapse __
421 install4jInternalId = applicationName
423 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
424 .replaceAll("_+", "") // collapse __
425 //.replaceAll("_*-_*", "-") // collapse _-_
426 install4jUnixApplicationFolder = applicationName
428 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
429 .replaceAll("_+", "_") // collapse __
430 .replaceAll("_*-_*", "-") // collapse _-_
433 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
434 getdownAppDir = string("${getdownAppBaseDir}/${getdownAppDistDir}")
435 //getdownJ11libDir = "${getdownAppBaseDir}/${getdown_j11lib_dir}"
436 getdownResourceDir = string("${getdownAppBaseDir}/${getdown_resource_dir}")
437 getdownInstallDir = string("${getdownAppBaseDir}/${getdown_install_dir}")
438 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
439 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
440 /* compile without modules -- using classpath libraries
441 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
442 modules_runtimeClasspath = modules_compileClasspath
447 apply plugin: "com.palantir.git-version"
448 def details = versionDetails()
449 gitHash = details.gitHash
450 gitBranch = details.branchName
451 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
452 println("Not in a git repository. Using git values from RELEASE properties file.")
453 gitHash = releaseProps.getProperty("git.hash")
454 gitBranch = releaseProps.getProperty("git.branch")
455 } catch(java.lang.RuntimeException e1) {
456 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
459 println("Using a ${CHANNEL} profile.")
461 additional_compiler_args = []
462 // configure classpath/args for j8/j11 compilation
463 if (JAVA_VERSION.equals("1.8")) {
464 JAVA_INTEGER_VERSION = string("8")
467 libDistDir = j8libDir
468 compile_source_compatibility = 1.8
469 compile_target_compatibility = 1.8
470 // these are getdown.txt properties defined dependent on the JAVA_VERSION
471 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
472 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
473 // this property is assigned below and expanded to multiple lines in the getdown task
474 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
475 // this property is for the Java library used in eclipse
476 eclipseJavaRuntimeName = string("JavaSE-1.8")
477 } else if (JAVA_VERSION.equals("11")) {
478 JAVA_INTEGER_VERSION = string("11")
480 libDistDir = j11libDir
481 compile_source_compatibility = 11
482 compile_target_compatibility = 11
483 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
484 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
485 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
486 eclipseJavaRuntimeName = string("JavaSE-11")
487 /* compile without modules -- using classpath libraries
488 additional_compiler_args += [
489 '--module-path', modules_compileClasspath.asPath,
490 '--add-modules', j11modules
493 } else if (JAVA_VERSION.equals("17")) {
494 JAVA_INTEGER_VERSION = string("17")
496 libDistDir = j17libDir
497 compile_source_compatibility = 17
498 compile_target_compatibility = 17
499 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
500 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
501 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
502 eclipseJavaRuntimeName = string("JavaSE-17")
503 /* compile without modules -- using classpath libraries
504 additional_compiler_args += [
505 '--module-path', modules_compileClasspath.asPath,
506 '--add-modules', j11modules
510 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
515 JAVA_MIN_VERSION = JAVA_VERSION
516 JAVA_MAX_VERSION = JAVA_VERSION
517 def jreInstallsDir = string(jre_installs_dir)
518 if (jreInstallsDir.startsWith("~/")) {
519 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
521 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
522 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
523 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
524 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
525 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
526 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
527 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
528 install4jConfFileName = string("jalview-install4j-conf.install4j")
529 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
530 install4jHomeDir = install4j_home_dir
531 if (install4jHomeDir.startsWith("~/")) {
532 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
535 resourceBuildDir = string("${buildDir}/resources")
536 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
537 helpBuildDir = string("${resourceBuildDir}/help_build")
538 docBuildDir = string("${resourceBuildDir}/doc_build")
540 if (buildProperties == null) {
541 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
543 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
544 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
545 helpSourceDir = string("${helpParentDir}/${help_dir}")
546 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
549 convertBinaryExpectedLocation = imagemagick_convert
550 if (convertBinaryExpectedLocation.startsWith("~/")) {
551 convertBinaryExpectedLocation = System.getProperty("user.home") + convertBinaryExpectedLocation.substring(1)
553 if (file(convertBinaryExpectedLocation).exists()) {
554 convertBinary = convertBinaryExpectedLocation
557 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
558 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
559 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
561 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
563 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
565 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
566 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
567 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
568 jalviewjsJalviewCoreHtmlFile = string("")
569 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
570 jalviewjsCoreClasslists = []
571 jalviewjsJalviewTemplateName = string(jalviewjs_name)
572 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
573 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
574 jalviewjsJ2sProps = null
575 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
577 eclipseWorkspace = null
578 eclipseBinary = string("")
579 eclipseVersion = string("")
589 outputDir = file(classesDir)
593 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
596 compileClasspath = files(sourceSets.main.java.outputDir)
597 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
599 runtimeClasspath = compileClasspath
600 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
605 srcDirs cloverInstrDir
606 outputDir = cloverClassesDir
610 srcDirs = sourceSets.main.resources.srcDirs
613 compileClasspath = files( sourceSets.clover.java.outputDir )
614 //compileClasspath += files( testClassesDir )
615 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
616 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
617 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
619 runtimeClasspath = compileClasspath
624 srcDirs testSourceDir
625 outputDir = file(testClassesDir)
629 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
632 compileClasspath = files( sourceSets.test.java.outputDir )
633 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
634 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
636 runtimeClasspath = compileClasspath
637 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
643 // eclipse project and settings files creation, also used by buildship
646 name = eclipse_project_name
648 natures 'org.eclipse.jdt.core.javanature',
649 'org.eclipse.jdt.groovy.core.groovyNature',
650 'org.eclipse.buildship.core.gradleprojectnature'
652 buildCommand 'org.eclipse.jdt.core.javabuilder'
653 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
657 //defaultOutputDir = sourceSets.main.java.outputDir
658 configurations.each{ c->
659 if (c.isCanBeResolved()) {
660 minusConfigurations += [c]
664 plusConfigurations = [ ]
668 def removeTheseToo = []
669 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
670 cp.entries.each { entry ->
671 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
672 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
673 // we add the resources and help/help dirs in as libs afterwards (see below)
674 if (entry.kind == 'src') {
675 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
676 removeTheseToo += entry
678 alreadyAddedSrcPath.putAt(entry.path, true)
683 cp.entries.removeAll(removeTheseToo)
685 //cp.entries += new Output("${eclipse_bin_dir}/main")
686 if (file(helpParentDir).isDirectory()) {
687 cp.entries += new Library(fileReference(helpParentDir))
689 if (file(resourceDir).isDirectory()) {
690 cp.entries += new Library(fileReference(resourceDir))
693 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
695 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
696 //don't want to add outputDir as eclipse is using its own output dir in bin/main
697 if (it.isDirectory() || ! it.exists()) {
698 // don't add dirs to classpath, especially if they don't exist
699 return false // groovy "continue" in .any closure
701 def itPath = it.toString()
702 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
703 // make relative path
704 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
706 if (alreadyAddedLibPath.get(itPath)) {
707 //println("Not adding duplicate entry "+itPath)
709 //println("Adding entry "+itPath)
710 cp.entries += new Library(fileReference(itPath))
711 alreadyAddedLibPath.put(itPath, true)
715 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
716 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
717 if (it.isDirectory() || ! it.exists()) {
718 // don't add dirs to classpath
719 return false // groovy "continue" in .any closure
722 def itPath = it.toString()
723 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
724 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
726 if (alreadyAddedLibPath.get(itPath)) {
729 def lib = new Library(fileReference(itPath))
730 lib.entryAttributes["test"] = "true"
732 alreadyAddedLibPath.put(itPath, true)
740 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
745 // for the IDE, use java 11 compatibility
746 sourceCompatibility = compile_source_compatibility
747 targetCompatibility = compile_target_compatibility
748 javaRuntimeName = eclipseJavaRuntimeName
750 // add in jalview project specific properties/preferences into eclipse core preferences
752 withProperties { props ->
753 def jalview_prefs = new Properties()
754 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
755 jalview_prefs.load(ins)
757 jalview_prefs.forEach { t, v ->
758 if (props.getAt(t) == null) {
762 // codestyle file -- overrides previous formatter prefs
763 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
764 if (csFile.exists()) {
765 XmlParser parser = new XmlParser()
766 def profiles = parser.parse(csFile)
767 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
768 if (profile != null) {
769 profile.'setting'.each { s ->
771 def value = s.'@value'
772 if (id != null && value != null) {
773 props.putAt(id, value)
784 // Don't want these to be activated if in headless build
785 synchronizationTasks "eclipseSynchronizationTask"
786 //autoBuildTasks "eclipseAutoBuildTask"
792 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
793 // Class to allow updating arbitrary properties files
794 class PropertiesFile extends PropertiesPersistableConfigurationObject {
795 public PropertiesFile(PropertiesTransformer t) { super(t); }
796 @Override protected void load(Properties properties) { }
797 @Override protected void store(Properties properties) { }
798 @Override protected String getDefaultResourceName() { return ""; }
799 // This is necessary, because PropertiesPersistableConfigurationObject fails
800 // if no default properties file exists.
801 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
804 // Task to update arbitrary properties files (set outputFile)
805 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
806 private final PropertiesFileContentMerger file;
807 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
808 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
809 protected void configure(PropertiesFile props) {
810 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
812 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
815 task eclipseUIPreferences(type: PropertiesFileTask) {
816 description = "Generate Eclipse additional settings"
817 def filename = "org.eclipse.jdt.ui.prefs"
818 outputFile = "$projectDir/.settings/${filename}" as File
821 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
826 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
827 description = "Generate Eclipse additional settings"
828 def filename = "org.eclipse.jdt.groovy.core.prefs"
829 outputFile = "$projectDir/.settings/${filename}" as File
832 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
837 task eclipseAllPreferences {
839 dependsOn eclipseUIPreferences
840 dependsOn eclipseGroovyCorePreferences
843 eclipseUIPreferences.mustRunAfter eclipseJdt
844 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
846 /* end of eclipse preferences hack */
854 delete cloverBuildDir
855 delete cloverReportDir
860 task cloverInstrJava(type: JavaExec) {
861 group = "Verification"
862 description = "Create clover instrumented source java files"
864 dependsOn cleanClover
866 inputs.files(sourceSets.main.allJava)
867 outputs.dir(cloverInstrDir)
869 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
870 classpath = sourceSets.clover.compileClasspath
871 main = "com.atlassian.clover.CloverInstr"
879 cloverInstrDir.getPath(),
881 def srcFiles = sourceSets.main.allJava.files
884 { file -> file.absolutePath }
887 args argsList.toArray()
890 delete cloverInstrDir
891 println("Clover: About to instrument "+srcFiles.size() +" files")
896 task cloverInstrTests(type: JavaExec) {
897 group = "Verification"
898 description = "Create clover instrumented source test files"
900 dependsOn cleanClover
902 inputs.files(testDir)
903 outputs.dir(cloverTestInstrDir)
905 classpath = sourceSets.clover.compileClasspath
906 main = "com.atlassian.clover.CloverInstr"
916 cloverTestInstrDir.getPath(),
918 args argsList.toArray()
921 delete cloverTestInstrDir
922 println("Clover: About to instrument test files")
928 group = "Verification"
929 description = "Create clover instrumented all source files"
931 dependsOn cloverInstrJava
932 dependsOn cloverInstrTests
936 cloverClasses.dependsOn cloverInstr
939 task cloverConsoleReport(type: JavaExec) {
940 group = "Verification"
941 description = "Creates clover console report"
944 file(cloverDb).exists()
947 inputs.dir cloverClassesDir
949 classpath = sourceSets.clover.runtimeClasspath
950 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
952 if (cloverreport_mem.length() > 0) {
953 maxHeapSize = cloverreport_mem
955 if (cloverreport_jvmargs.length() > 0) {
956 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
966 args argsList.toArray()
970 task cloverHtmlReport(type: JavaExec) {
971 group = "Verification"
972 description = "Creates clover HTML report"
975 file(cloverDb).exists()
978 def cloverHtmlDir = cloverReportDir
979 inputs.dir cloverClassesDir
980 outputs.dir cloverHtmlDir
982 classpath = sourceSets.clover.runtimeClasspath
983 main = "com.atlassian.clover.reporters.html.HtmlReporter"
985 if (cloverreport_mem.length() > 0) {
986 maxHeapSize = cloverreport_mem
988 if (cloverreport_jvmargs.length() > 0) {
989 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
1000 if (cloverreport_html_options.length() > 0) {
1001 argsList += cloverreport_html_options.split(" ")
1004 args argsList.toArray()
1008 task cloverXmlReport(type: JavaExec) {
1009 group = "Verification"
1010 description = "Creates clover XML report"
1013 file(cloverDb).exists()
1016 def cloverXmlFile = "${cloverReportDir}/clover.xml"
1017 inputs.dir cloverClassesDir
1018 outputs.file cloverXmlFile
1020 classpath = sourceSets.clover.runtimeClasspath
1021 main = "com.atlassian.clover.reporters.xml.XMLReporter"
1023 if (cloverreport_mem.length() > 0) {
1024 maxHeapSize = cloverreport_mem
1026 if (cloverreport_jvmargs.length() > 0) {
1027 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
1038 if (cloverreport_xml_options.length() > 0) {
1039 argsList += cloverreport_xml_options.split(" ")
1042 args argsList.toArray()
1047 group = "Verification"
1048 description = "Creates clover reports"
1050 dependsOn cloverXmlReport
1051 dependsOn cloverHtmlReport
1058 sourceCompatibility = compile_source_compatibility
1059 targetCompatibility = compile_target_compatibility
1060 options.compilerArgs += additional_compiler_args
1061 print ("Setting target compatibility to "+targetCompatibility+"\n")
1063 //classpath += configurations.cloverRuntime
1069 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1070 sourceCompatibility = compile_source_compatibility
1071 targetCompatibility = compile_target_compatibility
1072 options.compilerArgs = additional_compiler_args
1073 options.encoding = "UTF-8"
1075 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1082 sourceCompatibility = compile_source_compatibility
1083 targetCompatibility = compile_target_compatibility
1084 options.compilerArgs = additional_compiler_args
1086 print ("Setting target compatibility to "+targetCompatibility+"\n")
1093 delete sourceSets.main.java.outputDir
1099 dependsOn cleanClover
1101 delete sourceSets.test.java.outputDir
1106 // format is a string like date.format("dd MMMM yyyy")
1107 def getDate(format) {
1108 return date.format(format)
1112 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1113 MutableDataSet options = new MutableDataSet()
1115 def extensions = new ArrayList<>()
1116 extensions.add(AnchorLinkExtension.create())
1117 extensions.add(AutolinkExtension.create())
1118 extensions.add(StrikethroughExtension.create())
1119 extensions.add(TaskListExtension.create())
1120 extensions.add(TablesExtension.create())
1121 extensions.add(TocExtension.create())
1123 options.set(Parser.EXTENSIONS, extensions)
1125 // set GFM table parsing options
1126 options.set(TablesExtension.WITH_CAPTION, false)
1127 options.set(TablesExtension.COLUMN_SPANS, false)
1128 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1129 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1130 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1131 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1132 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1134 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1135 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1136 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1137 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1139 Parser parser = Parser.builder(options).build()
1140 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1142 mdFiles.each { mdFile ->
1143 // add table of contents
1144 def mdText = "[TOC]\n"+mdFile.text
1146 // grab the first top-level title
1148 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1149 def matcher = mdText =~ titleRegex
1150 if (matcher.size() > 0) {
1151 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1152 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1154 // or use the filename if none found
1155 if (title == null) {
1156 title = mdFile.getName()
1159 Node document = parser.parse(mdText)
1160 String htmlBody = renderer.render(document)
1161 def htmlText = '''<html>
1162 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1163 <html xmlns="http://www.w3.org/1999/xhtml">
1165 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1166 <meta http-equiv="Content-Style-Type" content="text/css" />
1167 <meta name="generator" content="flexmark" />
1169 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1171 <style type="text/css">code{white-space: pre;}</style>
1173 htmlText += ((cssFile != null) ? cssFile.text : '')
1174 htmlText += '''</head>
1177 htmlText += htmlBody
1183 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1184 def htmlFile = file(htmlFilePath)
1185 println("Creating ${htmlFilePath}")
1186 htmlFile.text = htmlText
1191 task copyDocs(type: Copy) {
1192 def inputDir = "${jalviewDir}/${doc_dir}"
1193 def outputDir = "${docBuildDir}/${doc_dir}"
1197 include('**/*.html')
1199 filter(ReplaceTokens,
1203 'Version-Rel': JALVIEW_VERSION,
1204 'Year-Rel': getDate("yyyy")
1211 exclude('**/*.html')
1216 inputs.dir(inputDir)
1217 outputs.dir(outputDir)
1221 task convertMdFiles {
1223 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1224 def cssFile = file("${jalviewDir}/${flexmark_css}")
1227 convertMdToHtml(mdFiles, cssFile)
1230 inputs.files(mdFiles)
1231 inputs.file(cssFile)
1234 mdFiles.each { mdFile ->
1235 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1236 htmlFiles.add(file(htmlFilePath))
1238 outputs.files(htmlFiles)
1242 def hugoTemplateSubstitutions(String input, Map extras=null) {
1243 def replacements = [
1244 DATE: getDate("yyyy-MM-dd"),
1245 CHANNEL: propertiesChannelName,
1246 APPLICATION_NAME: applicationName,
1248 GIT_BRANCH: gitBranch,
1249 VERSION: JALVIEW_VERSION,
1250 JAVA_VERSION: JAVA_VERSION,
1251 VERSION_UNDERSCORES: JALVIEW_VERSION_UNDERSCORES,
1256 if (extras != null) {
1257 extras.each{ k, v ->
1258 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1261 replacements.each{ k, v ->
1262 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1267 def mdFileComponents(File mdFile, def dateOnly=false) {
1270 if (mdFile.exists()) {
1271 def inFrontMatter = false
1272 def firstLine = true
1273 mdFile.eachLine { line ->
1274 if (line.matches("---")) {
1275 def prev = inFrontMatter
1276 inFrontMatter = firstLine
1277 if (inFrontMatter != prev)
1280 if (inFrontMatter) {
1282 if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
1283 map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
1284 } else if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
1285 map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
1286 } else if (m = line =~ /^channel:\s*(\S+)/) {
1287 map["channel"] = m[0][1]
1288 } else if (m = line =~ /^version:\s*(\S+)/) {
1289 map["version"] = m[0][1]
1290 } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
1291 map[ m[0][1] ] = m[0][2]
1293 if (dateOnly && map["date"] != null) {
1299 content += line+"\n"
1304 return dateOnly ? map["date"] : [map, content]
1307 task hugoTemplates {
1309 description "Create partially populated md pages for hugo website build"
1311 def hugoTemplatesDir = file("${jalviewDir}/${hugo_templates_dir}")
1312 def hugoBuildDir = "${jalviewDir}/${hugo_build_dir}"
1313 def templateFiles = fileTree(dir: hugoTemplatesDir)
1314 def releaseMdFile = file("${jalviewDir}/${releases_dir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1315 def whatsnewMdFile = file("${jalviewDir}/${whatsnew_dir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1316 def oldJvlFile = file("${jalviewDir}/${hugo_old_jvl}")
1317 def jalviewjsFile = file("${jalviewDir}/${hugo_jalviewjs}")
1320 // specific release template for version archive
1323 def givenDate = null
1324 def givenChannel = null
1325 def givenVersion = null
1326 if (CHANNEL == "RELEASE") {
1327 def (map, content) = mdFileComponents(releaseMdFile)
1328 givenDate = map.date
1329 givenChannel = map.channel
1330 givenVersion = map.version
1332 if (givenVersion != null && givenVersion != JALVIEW_VERSION) {
1333 throw new GradleException("'version' header (${givenVersion}) found in ${releaseMdFile} does not match JALVIEW_VERSION (${JALVIEW_VERSION})")
1336 if (whatsnewMdFile.exists())
1337 whatsnew = whatsnewMdFile.text
1340 def oldJvl = oldJvlFile.exists() ? oldJvlFile.collect{it} : []
1341 def jalviewjsLink = jalviewjsFile.exists() ? jalviewjsFile.collect{it} : []
1343 def changesHugo = null
1344 if (changes != null) {
1345 changesHugo = '<div class="release_notes">\n\n'
1346 def inSection = false
1347 changes.eachLine { line ->
1349 if (m = line =~ /^##([^#].*)$/) {
1351 changesHugo += "</div>\n\n"
1353 def section = m[0][1].trim()
1354 section = section.toLowerCase()
1355 section = section.replaceAll(/ +/, "_")
1356 section = section.replaceAll(/[^a-z0-9_\-]/, "")
1357 changesHugo += "<div class=\"${section}\">\n\n"
1359 } else if (m = line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
1360 def comment = m[0][2].trim()
1361 if (comment != "") {
1362 comment = comment.replaceAll('"', """)
1364 comment.eachMatch(/JAL-\d+/) { jal -> issuekeys += jal }
1365 def newline = m[0][1]
1366 if (comment.trim() != "")
1367 newline += "{{<comment>}}${comment}{{</comment>}} "
1368 newline += m[0][3].trim()
1369 if (issuekeys.size() > 0)
1370 newline += " {{< jal issue=\"${issuekeys.join(",")}\" alt=\"${comment}\" >}}"
1371 if (m[0][4] != null)
1376 changesHugo += line+"\n"
1379 changesHugo += "\n</div>\n\n"
1381 changesHugo += '</div>'
1384 templateFiles.each{ templateFile ->
1385 def newFileName = string(hugoTemplateSubstitutions(templateFile.getName()))
1386 def relPath = hugoTemplatesDir.toPath().relativize(templateFile.toPath()).getParent()
1387 def newRelPathName = hugoTemplateSubstitutions( relPath.toString() )
1389 def outPathName = string("${hugoBuildDir}/$newRelPathName")
1393 rename(templateFile.getName(), newFileName)
1397 def newFile = file("${outPathName}/${newFileName}".toString())
1398 def content = newFile.text
1399 newFile.text = hugoTemplateSubstitutions(content,
1402 CHANGES: changesHugo,
1403 DATE: givenDate == null ? "" : givenDate.format("yyyy-MM-dd"),
1404 DRAFT: givenDate == null ? "true" : "false",
1405 JALVIEWJSLINK: jalviewjsLink.contains(JALVIEW_VERSION) ? "true" : "false",
1406 JVL_HEADER: oldJvl.contains(JALVIEW_VERSION) ? "jvl: true" : ""
1413 inputs.file(oldJvlFile)
1414 inputs.dir(hugoTemplatesDir)
1415 inputs.property("JALVIEW_VERSION", { JALVIEW_VERSION })
1416 inputs.property("CHANNEL", { CHANNEL })
1419 def getMdDate(File mdFile) {
1420 return mdFileComponents(mdFile, true)
1423 def getMdSections(String content) {
1425 def sectionContent = ""
1426 def sectionName = null
1427 content.eachLine { line ->
1429 if (m = line =~ /^##([^#].*)$/) {
1430 if (sectionName != null) {
1431 sections[sectionName] = sectionContent
1435 sectionName = m[0][1].trim()
1436 sectionName = sectionName.toLowerCase()
1437 sectionName = sectionName.replaceAll(/ +/, "_")
1438 sectionName = sectionName.replaceAll(/[^a-z0-9_\-]/, "")
1439 } else if (sectionName != null) {
1440 sectionContent += line+"\n"
1443 if (sectionContent != null) {
1444 sections[sectionName] = sectionContent
1448 task copyHelp(type: Copy) {
1449 def inputDir = helpSourceDir
1450 def outputDir = "${helpBuildDir}/${help_dir}"
1454 include('**/*.html')
1458 filter(ReplaceTokens,
1462 'Version-Rel': JALVIEW_VERSION,
1463 'Year-Rel': getDate("yyyy")
1470 exclude('**/*.html')
1477 inputs.dir(inputDir)
1478 outputs.files(helpFile)
1479 outputs.dir(outputDir)
1483 task releasesTemplates {
1485 description "Recreate whatsNew.html and releases.html from markdown files and templates in help"
1489 def releasesTemplateFile = file("${jalviewDir}/${releases_template}")
1490 def whatsnewTemplateFile = file("${jalviewDir}/${whatsnew_template}")
1491 def releasesHtmlFile = file("${helpBuildDir}/${help_dir}/${releases_html}")
1492 def whatsnewHtmlFile = file("${helpBuildDir}/${help_dir}/${whatsnew_html}")
1493 def releasesMdDir = "${jalviewDir}/${releases_dir}"
1494 def whatsnewMdDir = "${jalviewDir}/${whatsnew_dir}"
1497 def releaseMdFile = file("${releasesMdDir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1498 def whatsnewMdFile = file("${whatsnewMdDir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1500 if (CHANNEL == "RELEASE") {
1501 if (!releaseMdFile.exists()) {
1502 throw new GradleException("File ${releaseMdFile} must be created for RELEASE")
1504 if (!whatsnewMdFile.exists()) {
1505 throw new GradleException("File ${whatsnewMdFile} must be created for RELEASE")
1509 def releaseFiles = fileTree(dir: releasesMdDir, include: "release-*.md")
1510 def releaseFilesDates = releaseFiles.collectEntries {
1511 [(it): getMdDate(it)]
1513 releaseFiles = releaseFiles.sort { a,b -> releaseFilesDates[a].compareTo(releaseFilesDates[b]) }
1515 def releasesTemplate = releasesTemplateFile.text
1516 def m = releasesTemplate =~ /(?s)__VERSION_LOOP_START__(.*)__VERSION_LOOP_END__/
1517 def versionTemplate = m[0][1]
1519 MutableDataSet options = new MutableDataSet()
1521 def extensions = new ArrayList<>()
1522 options.set(Parser.EXTENSIONS, extensions)
1523 options.set(Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE, true)
1525 Parser parser = Parser.builder(options).build()
1526 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1528 def actualVersions = releaseFiles.collect { rf ->
1529 def (rfMap, rfContent) = mdFileComponents(rf)
1530 return rfMap.version
1532 def versionsHtml = ""
1533 def linkedVersions = []
1534 releaseFiles.reverse().each { rFile ->
1535 def (rMap, rContent) = mdFileComponents(rFile)
1537 def versionLink = ""
1538 def partialVersion = ""
1539 def firstPart = true
1540 rMap.version.split("\\.").each { part ->
1541 def displayPart = ( firstPart ? "" : "." ) + part
1542 partialVersion += displayPart
1544 linkedVersions.contains(partialVersion)
1545 || ( actualVersions.contains(partialVersion) && partialVersion != rMap.version )
1547 versionLink += displayPart
1549 versionLink += "<a id=\"Jalview.${partialVersion}\">${displayPart}</a>"
1550 linkedVersions += partialVersion
1554 def displayDate = releaseFilesDates[rFile].format("dd/MM/yyyy")
1557 def rContentProcessed = ""
1558 rContent.eachLine { line ->
1559 if (lm = line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
1560 line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}"
1561 } else if (lm = line =~ /^###([^#]+.*)$/) {
1562 line = "_${lm[0][1].trim()}_"
1564 rContentProcessed += line + "\n"
1567 def rContentSections = getMdSections(rContentProcessed)
1568 def rVersion = versionTemplate
1569 if (rVersion != "") {
1570 def rNewFeatures = rContentSections["new_features"]
1571 def rIssuesResolved = rContentSections["issues_resolved"]
1572 Node newFeaturesNode = parser.parse(rNewFeatures)
1573 String newFeaturesHtml = renderer.render(newFeaturesNode)
1574 Node issuesResolvedNode = parser.parse(rIssuesResolved)
1575 String issuesResolvedHtml = renderer.render(issuesResolvedNode)
1576 rVersion = hugoTemplateSubstitutions(rVersion,
1578 VERSION: rMap.version,
1579 VERSION_LINK: versionLink,
1580 DISPLAY_DATE: displayDate,
1581 NEW_FEATURES: newFeaturesHtml,
1582 ISSUES_RESOLVED: issuesResolvedHtml
1585 versionsHtml += rVersion
1589 releasesTemplate = releasesTemplate.replaceAll("(?s)__VERSION_LOOP_START__.*__VERSION_LOOP_END__", versionsHtml)
1590 releasesTemplate = hugoTemplateSubstitutions(releasesTemplate)
1591 releasesHtmlFile.text = releasesTemplate
1593 if (whatsnewMdFile.exists()) {
1594 def wnDisplayDate = releaseFilesDates[releaseMdFile] != null ? releaseFilesDates[releaseMdFile].format("dd MMMM yyyy") : ""
1595 def whatsnewMd = hugoTemplateSubstitutions(whatsnewMdFile.text)
1596 Node whatsnewNode = parser.parse(whatsnewMd)
1597 String whatsnewHtml = renderer.render(whatsnewNode)
1598 whatsnewHtml = whatsnewTemplateFile.text.replaceAll("__WHATS_NEW__", whatsnewHtml)
1599 whatsnewHtmlFile.text = hugoTemplateSubstitutions(whatsnewHtml,
1601 VERSION: JALVIEW_VERSION,
1602 DISPLAY_DATE: wnDisplayDate
1605 } else if (gradle.taskGraph.hasTask(":linkCheck")) {
1606 whatsnewHtmlFile.text = "Development build " + getDate("yyyy-MM-dd HH:mm:ss")
1611 inputs.file(releasesTemplateFile)
1612 inputs.file(whatsnewTemplateFile)
1613 inputs.dir(releasesMdDir)
1614 inputs.dir(whatsnewMdDir)
1615 outputs.file(releasesHtmlFile)
1616 outputs.file(whatsnewHtmlFile)
1618 task copyResources(type: Copy) {
1620 description = "Copy (and make text substitutions in) the resources dir to the build area"
1622 def inputDir = resourceDir
1623 def outputDir = resourcesBuildDir
1627 include('**/*.html')
1629 filter(ReplaceTokens,
1633 'Version-Rel': JALVIEW_VERSION,
1634 'Year-Rel': getDate("yyyy")
1641 exclude('**/*.html')
1646 inputs.dir(inputDir)
1647 outputs.dir(outputDir)
1650 task copyChannelResources(type: Copy) {
1651 dependsOn copyResources
1653 description = "Copy the channel resources dir to the build resources area"
1655 def inputDir = "${channelDir}/${resource_dir}"
1656 def outputDir = resourcesBuildDir
1658 include(channel_props)
1659 filter(ReplaceTokens,
1663 'SUFFIX': channelSuffix
1668 exclude(channel_props)
1672 inputs.dir(inputDir)
1673 outputs.dir(outputDir)
1676 task createBuildProperties(type: WriteProperties) {
1677 dependsOn copyResources
1679 description = "Create the ${buildProperties} file"
1681 inputs.dir(sourceDir)
1682 inputs.dir(resourcesBuildDir)
1683 outputFile (buildProperties)
1684 // taking time specific comment out to allow better incremental builds
1685 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1686 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1687 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1688 property "VERSION", JALVIEW_VERSION
1689 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1690 property "JAVA_COMPILE_VERSION", JAVA_INTEGER_VERSION
1691 if (getdownSetAppBaseProperty) {
1692 property "GETDOWNAPPBASE", getdownAppBase
1693 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1695 outputs.file(outputFile)
1699 task buildIndices(type: JavaExec) {
1701 classpath = sourceSets.main.compileClasspath
1702 main = "com.sun.java.help.search.Indexer"
1703 workingDir = "${helpBuildDir}/${help_dir}"
1706 inputs.dir("${workingDir}/${argDir}")
1708 outputs.dir("${classesDir}/doc")
1709 outputs.dir("${classesDir}/help")
1710 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1711 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1712 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1713 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1714 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1715 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1718 task buildResources {
1719 dependsOn copyResources
1720 dependsOn copyChannelResources
1721 dependsOn createBuildProperties
1725 dependsOn buildResources
1728 dependsOn releasesTemplates
1729 dependsOn convertMdFiles
1730 dependsOn buildIndices
1734 compileJava.dependsOn prepare
1735 run.dependsOn compileJava
1736 //run.dependsOn prepare
1739 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1744 dependsOn cloverClasses
1746 dependsOn compileJava //?
1750 includeGroups testng_groups
1751 excludeGroups testng_excluded_groups
1753 useDefaultListeners=true
1754 // Uncomment to show stdout and stderr for tests in gradle build output
1755 // testLogging.showStandardStreams = true
1758 maxHeapSize = "1024m"
1760 workingDir = jalviewDir
1761 def testLaf = project.findProperty("test_laf")
1762 if (testLaf != null) {
1763 println("Setting Test LaF to '${testLaf}'")
1764 systemProperty "laf", testLaf
1766 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1767 if (testHiDPIScale != null) {
1768 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1769 systemProperty "sun.java2d.uiScale", testHiDPIScale
1771 sourceCompatibility = compile_source_compatibility
1772 targetCompatibility = compile_target_compatibility
1773 jvmArgs += additional_compiler_args
1777 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1783 task compileLinkCheck(type: JavaCompile) {
1785 classpath = files("${jalviewDir}/${utils_dir}")
1786 destinationDir = file("${jalviewDir}/${utils_dir}")
1787 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1789 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1790 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1791 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1792 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1796 task linkCheck(type: JavaExec) {
1798 dependsOn compileLinkCheck
1800 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1801 classpath = files("${jalviewDir}/${utils_dir}")
1802 main = "HelpLinksChecker"
1803 workingDir = "${helpBuildDir}"
1804 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1806 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1807 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1810 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1814 inputs.dir(helpBuildDir)
1815 outputs.file(helpLinksCheckerOutFile)
1819 // import the pubhtmlhelp target
1820 ant.properties.basedir = "${jalviewDir}"
1821 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1822 ant.importBuild "${utils_dir}/publishHelp.xml"
1825 task cleanPackageDir(type: Delete) {
1827 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1837 attributes "Main-Class": main_class,
1838 "Permissions": "all-permissions",
1839 "Application-Name": applicationName,
1840 "Codebase": application_codebase,
1841 "Implementation-Version": JALVIEW_VERSION
1844 def outputDir = "${jalviewDir}/${package_dir}"
1845 destinationDirectory = file(outputDir)
1846 archiveFileName = rootProject.name+".jar"
1847 duplicatesStrategy "EXCLUDE"
1854 exclude "**/*.jar.*"
1856 inputs.dir(sourceSets.main.java.outputDir)
1857 sourceSets.main.resources.srcDirs.each{ dir ->
1860 outputs.file("${outputDir}/${archiveFileName}")
1864 task copyJars(type: Copy) {
1865 from fileTree(dir: classesDir, include: "**/*.jar").files
1866 into "${jalviewDir}/${package_dir}"
1870 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1871 task syncJars(type: Sync) {
1873 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1874 into "${jalviewDir}/${package_dir}"
1876 include jar.archiveFileName.getOrNull()
1883 description = "Put all required libraries in dist"
1884 // order of "cleanPackageDir", "copyJars", "jar" important!
1885 jar.mustRunAfter cleanPackageDir
1886 syncJars.mustRunAfter cleanPackageDir
1887 dependsOn cleanPackageDir
1890 outputs.dir("${jalviewDir}/${package_dir}")
1895 dependsOn cleanPackageDir
1902 group = "distribution"
1903 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1907 from ("${jalviewDir}/${libDistDir}") {
1911 attributes "Implementation-Version": JALVIEW_VERSION,
1912 "Application-Name": applicationName
1915 duplicatesStrategy "INCLUDE"
1917 mainClassName = shadow_jar_main_class
1919 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1923 task getdownImagesCopy() {
1924 inputs.dir getdownImagesDir
1925 outputs.dir getdownImagesBuildDir
1929 from(getdownImagesDir) {
1930 include("*getdown*.png")
1932 into getdownImagesBuildDir
1937 task getdownImagesProcess() {
1938 dependsOn getdownImagesCopy
1941 if (backgroundImageText) {
1942 if (convertBinary == null) {
1943 throw new StopExecutionException("No ImageMagick convert binary installed at '${convertBinaryExpectedLocation}'")
1945 if (!project.hasProperty("getdown_background_image_text_suffix_cmd")) {
1946 throw new StopExecutionException("No property 'getdown_background_image_text_suffix_cmd' defined. See channel_gradle.properties for channel ${CHANNEL}")
1948 fileTree(dir: getdownImagesBuildDir, include: "*background*.png").getFiles().each { file ->
1950 executable convertBinary
1953 '-font', getdown_background_image_text_font,
1954 '-fill', getdown_background_image_text_colour,
1955 '-draw', sprintf(getdown_background_image_text_suffix_cmd, channelSuffix),
1956 '-draw', sprintf(getdown_background_image_text_commit_cmd, "git-commit: ${gitHash}"),
1957 '-draw', sprintf(getdown_background_image_text_date_cmd, getDate("yyyy-MM-dd HH:mm:ss")),
1966 task getdownImages() {
1967 dependsOn getdownImagesProcess
1970 task getdownWebsite() {
1971 group = "distribution"
1972 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1974 dependsOn getdownImages
1979 def getdownWebsiteResourceFilenames = []
1980 def getdownResourceDir = getdownResourceDir
1981 def getdownResourceFilenames = []
1984 // clean the getdown website and files dir before creating getdown folders
1985 delete getdownAppBaseDir
1986 delete getdownFilesDir
1989 from buildProperties
1990 rename(file(buildProperties).getName(), getdown_build_properties)
1993 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1996 from channelPropsFile
1997 filter(ReplaceTokens,
2001 'SUFFIX': channelSuffix
2004 into getdownAppBaseDir
2006 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
2008 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
2009 def props = project.properties.sort { it.key }
2010 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
2011 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
2013 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
2014 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
2016 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
2017 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
2019 if (getdownImagesBuildDir != null && file(getdownImagesBuildDir).exists()) {
2020 props.put("getdown_txt_ui.background_image", "${getdownImagesBuildDir}/${getdown_background_image}")
2021 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesBuildDir}/${getdown_instant_background_image}")
2022 props.put("getdown_txt_ui.error_background", "${getdownImagesBuildDir}/${getdown_error_background}")
2023 props.put("getdown_txt_ui.progress_image", "${getdownImagesBuildDir}/${getdown_progress_image}")
2024 props.put("getdown_txt_ui.icon", "${getdownImagesBuildDir}/${getdown_icon}")
2025 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesBuildDir}/${getdown_mac_dock_icon}")
2028 props.put("getdown_txt_title", jalview_name)
2029 props.put("getdown_txt_ui.name", applicationName)
2031 // start with appbase
2032 getdownTextLines += "appbase = ${getdownAppBase}"
2033 props.each{ prop, val ->
2034 if (prop.startsWith("getdown_txt_") && val != null) {
2035 if (prop.startsWith("getdown_txt_multi_")) {
2036 def key = prop.substring(18)
2037 val.split(",").each{ v ->
2038 def line = "${key} = ${v}"
2039 getdownTextLines += line
2042 // file values rationalised
2043 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
2045 if (val.indexOf('/') == 0) {
2048 } else if (val.indexOf('/') > 0) {
2049 // relative path (relative to jalviewDir)
2050 r = file( "${jalviewDir}/${val}" )
2053 val = "${getdown_resource_dir}/" + r.getName()
2054 getdownWebsiteResourceFilenames += val
2055 getdownResourceFilenames += r.getPath()
2058 if (! prop.startsWith("getdown_txt_resource")) {
2059 def line = prop.substring(12) + " = ${val}"
2060 getdownTextLines += line
2066 getdownWebsiteResourceFilenames.each{ filename ->
2067 getdownTextLines += "resource = ${filename}"
2069 getdownResourceFilenames.each{ filename ->
2072 into getdownResourceDir
2076 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
2077 getdownWrapperScripts.each{ script ->
2078 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
2082 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
2084 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
2089 fileTree(file(package_dir)).each{ f ->
2090 if (f.isDirectory()) {
2091 def files = fileTree(dir: f, include: ["*"]).getFiles()
2093 } else if (f.exists()) {
2097 def jalviewJar = jar.archiveFileName.getOrNull()
2098 // put jalview.jar first for CLASSPATH and .properties files reasons
2099 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
2100 def name = f.getName()
2101 def line = "code = ${getdownAppDistDir}/${name}"
2102 getdownTextLines += line
2109 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
2111 if (JAVA_VERSION.equals("11")) {
2112 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
2113 j11libFiles.sort().each{f ->
2114 def name = f.getName()
2115 def line = "code = ${getdown_j11lib_dir}/${name}"
2116 getdownTextLines += line
2119 into getdownJ11libDir
2125 // getdown-launcher.jar should not be in main application class path so the main application can move it when updated. Listed as a resource so it gets updated.
2126 //getdownTextLines += "class = " + file(getdownLauncher).getName()
2127 getdownTextLines += "resource = ${getdown_launcher_new}"
2128 getdownTextLines += "class = ${main_class}"
2129 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
2130 if (getdownSetAppBaseProperty) {
2131 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
2132 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
2135 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
2136 getdownTxt.write(getdownTextLines.join("\n"))
2138 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
2139 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
2140 launchJvl.write("appbase=${getdownAppBase}")
2142 // files going into the getdown website dir: getdown-launcher.jar
2144 from getdownLauncher
2145 rename(file(getdownLauncher).getName(), getdown_launcher_new)
2146 into getdownAppBaseDir
2149 // files going into the getdown website dir: getdown-launcher(-local).jar
2151 from getdownLauncher
2152 if (file(getdownLauncher).getName() != getdown_launcher) {
2153 rename(file(getdownLauncher).getName(), getdown_launcher)
2155 into getdownAppBaseDir
2158 // files going into the getdown website dir: ./install dir and files
2159 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
2162 from getdownLauncher
2163 from "${getdownAppDir}/${getdown_build_properties}"
2164 if (file(getdownLauncher).getName() != getdown_launcher) {
2165 rename(file(getdownLauncher).getName(), getdown_launcher)
2167 into getdownInstallDir
2170 // and make a copy in the getdown files dir (these are not downloaded by getdown)
2172 from getdownInstallDir
2173 into getdownFilesInstallDir
2177 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2181 from getdownLauncher
2182 from "${getdownAppBaseDir}/${getdown_build_properties}"
2183 from "${getdownAppBaseDir}/${channel_props}"
2184 if (file(getdownLauncher).getName() != getdown_launcher) {
2185 rename(file(getdownLauncher).getName(), getdown_launcher)
2187 into getdownFilesDir
2190 // and ./resource (not all downloaded by getdown)
2192 from getdownResourceDir
2193 into "${getdownFilesDir}/${getdown_resource_dir}"
2198 inputs.dir("${jalviewDir}/${package_dir}")
2200 outputs.dir(getdownAppBaseDir)
2201 outputs.dir(getdownFilesDir)
2205 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
2206 task getdownDigestDir(type: JavaExec) {
2208 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
2210 def digestDirPropertyName = "DIGESTDIR"
2212 classpath = files(getdownLauncher)
2213 def digestDir = findProperty(digestDirPropertyName)
2214 if (digestDir == null) {
2215 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
2219 main = "com.threerings.getdown.tools.Digester"
2223 task getdownDigest(type: JavaExec) {
2224 group = "distribution"
2225 description = "Digest the getdown website folder"
2226 dependsOn getdownWebsite
2228 classpath = files(getdownLauncher)
2230 main = "com.threerings.getdown.tools.Digester"
2231 args getdownAppBaseDir
2232 inputs.dir(getdownAppBaseDir)
2233 outputs.file("${getdownAppBaseDir}/digest2.txt")
2238 group = "distribution"
2239 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
2240 dependsOn getdownDigest
2242 if (reportRsyncCommand) {
2243 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
2244 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
2245 println "LIKELY RSYNC COMMAND:"
2246 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
2247 if (RUNRSYNC == "true") {
2249 commandLine "mkdir", "-p", toDir
2252 commandLine "rsync", "-avh", "--delete", fromDir, toDir
2260 task getdownArchiveBuild() {
2261 group = "distribution"
2262 description = "Put files in the archive dir to go on the website"
2264 dependsOn getdownWebsite
2266 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
2267 def vDir = "${getdownArchiveDir}/${v}"
2268 getdownFullArchiveDir = "${vDir}/getdown"
2269 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
2271 def vAltDir = "alt_${v}"
2272 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
2275 // cleanup old "old" dir
2276 delete getdownArchiveDir
2278 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
2279 getdownArchiveTxt.getParentFile().mkdirs()
2280 def getdownArchiveTextLines = []
2281 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
2285 from "${getdownAppBaseDir}/${getdownAppDistDir}"
2286 into "${getdownFullArchiveDir}/${vAltDir}"
2289 getdownTextLines.each { line ->
2290 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
2291 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
2292 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
2293 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
2294 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
2295 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
2296 // remove the existing resource = resource/ or bin/ lines
2297 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
2298 getdownArchiveTextLines += line
2302 // the resource dir -- add these files as resource lines in getdown.txt
2304 from "${archiveImagesDir}"
2305 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
2307 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
2311 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
2313 def vLaunchJvl = file(getdownVersionLaunchJvl)
2314 vLaunchJvl.getParentFile().mkdirs()
2315 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
2316 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
2317 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
2318 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
2319 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
2320 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
2322 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2324 from getdownLauncher
2325 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
2326 from "${getdownAppBaseDir}/${getdown_launcher_new}"
2327 from "${getdownAppBaseDir}/${channel_props}"
2328 if (file(getdownLauncher).getName() != getdown_launcher) {
2329 rename(file(getdownLauncher).getName(), getdown_launcher)
2331 into getdownFullArchiveDir
2337 task getdownArchiveDigest(type: JavaExec) {
2338 group = "distribution"
2339 description = "Digest the getdown archive folder"
2341 dependsOn getdownArchiveBuild
2344 classpath = files(getdownLauncher)
2345 args getdownFullArchiveDir
2347 main = "com.threerings.getdown.tools.Digester"
2348 inputs.dir(getdownFullArchiveDir)
2349 outputs.file("${getdownFullArchiveDir}/digest2.txt")
2352 task getdownArchive() {
2353 group = "distribution"
2354 description = "Build the website archive dir with getdown digest"
2356 dependsOn getdownArchiveBuild
2357 dependsOn getdownArchiveDigest
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')
2413 // turn off checksum creation for LOCAL channel
2414 def e = install4jConfigXml.application[0]
2415 e.'@createChecksums' = string(install4jCheckSums)
2417 // put file association actions where placeholder action is
2418 def install4jFileAssociationsText = install4jFileAssociationsFile.text
2419 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
2420 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
2421 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
2422 def parent = a.parent()
2424 fileAssociationActions.each { faa ->
2427 // don't need to continue in .any loop once replacements have been made
2432 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
2433 // NB we're deleting the /other/ one!
2434 // Also remove the examples subdir from non-release versions
2435 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
2436 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
2437 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
2438 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
2440 // remove the examples subdir from Full File Set
2441 def files = install4jConfigXml.files[0]
2442 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
2443 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
2444 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
2445 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
2446 dirEntry.parent().remove(dirEntry)
2448 install4jConfigXml.'**'.action.any { a ->
2449 if (a.'@customizedId' == customizedIdToDelete) {
2450 def parent = a.parent()
2456 // write install4j file
2457 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2464 delete install4jConfFile
2468 task cleanInstallersDataFiles {
2469 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2470 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2471 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2473 delete installersOutputTxt
2474 delete installersSha256
2475 delete hugoDataJsonFile
2479 task install4jDMGBackgroundImageCopy {
2480 inputs.file "${install4jDMGBackgroundImageDir}/${install4jDMGBackgroundImageFile}"
2481 outputs.dir "${install4jDMGBackgroundImageBuildDir}"
2484 from(install4jDMGBackgroundImageDir) {
2485 include(install4jDMGBackgroundImageFile)
2487 into install4jDMGBackgroundImageBuildDir
2492 task install4jDMGBackgroundImageProcess {
2493 dependsOn install4jDMGBackgroundImageCopy
2496 if (backgroundImageText) {
2497 if (convertBinary == null) {
2498 throw new StopExecutionException("No ImageMagick convert binary installed at '${convertBinaryExpectedLocation}'")
2500 if (!project.hasProperty("install4j_background_image_text_suffix_cmd")) {
2501 throw new StopExecutionException("No property 'install4j_background_image_text_suffix_cmd' defined. See channel_gradle.properties for channel ${CHANNEL}")
2503 fileTree(dir: install4jDMGBackgroundImageBuildDir, include: "*.png").getFiles().each { file ->
2505 executable convertBinary
2508 '-font', install4j_background_image_text_font,
2509 '-fill', install4j_background_image_text_colour,
2510 '-draw', sprintf(install4j_background_image_text_suffix_cmd, channelSuffix),
2511 '-draw', sprintf(install4j_background_image_text_commit_cmd, "git-commit: ${gitHash}"),
2512 '-draw', sprintf(install4j_background_image_text_date_cmd, getDate("yyyy-MM-dd HH:mm:ss")),
2521 task install4jDMGBackgroundImage {
2522 dependsOn install4jDMGBackgroundImageProcess
2525 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2526 group = "distribution"
2527 description = "Create the install4j installers"
2529 dependsOn copyInstall4jTemplate
2530 dependsOn cleanInstallersDataFiles
2531 dependsOn install4jDMGBackgroundImage
2533 projectFile = install4jConfFile
2535 // create an md5 for the input files to use as version for install4j conf file
2536 def digest = MessageDigest.getInstance("MD5")
2538 (file("${install4jDir}/${install4j_template}").text +
2539 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2540 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2541 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2542 if (filesMd5.length() >= 8) {
2543 filesMd5 = filesMd5.substring(0,8)
2545 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2548 'JALVIEW_NAME': jalview_name,
2549 'JALVIEW_APPLICATION_NAME': applicationName,
2550 'JALVIEW_DIR': "../..",
2551 'OSX_KEYSTORE': OSX_KEYSTORE,
2552 'OSX_APPLEID': OSX_APPLEID,
2553 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2554 'JSIGN_SH': JSIGN_SH,
2555 'JRE_DIR': getdown_app_dir_java,
2556 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2557 'JALVIEW_VERSION': JALVIEW_VERSION,
2558 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2559 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2560 'JAVA_VERSION': JAVA_VERSION,
2561 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2562 'VERSION': JALVIEW_VERSION,
2563 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2564 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2565 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2566 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2567 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2568 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2569 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2570 'BUNDLE_ID': install4jBundleId,
2571 'INTERNAL_ID': install4jInternalId,
2572 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2573 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2574 'MACOS_DMG_BG_IMAGE': "${install4jDMGBackgroundImageBuildDir}/${install4jDMGBackgroundImageFile}",
2575 'WRAPPER_LINK': getdownWrapperLink,
2576 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2577 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2578 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2579 'INSTALLER_NAME': install4jInstallerName,
2580 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2581 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2582 'GETDOWN_FILES_DIR': getdown_files_dir,
2583 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2584 'GETDOWN_DIST_DIR': getdownAppDistDir,
2585 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2586 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2587 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2588 'BUILD_DIR': install4jBuildDir,
2589 'APPLICATION_CATEGORIES': install4j_application_categories,
2590 'APPLICATION_FOLDER': install4jApplicationFolder,
2591 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2592 'EXECUTABLE_NAME': install4jExecutableName,
2593 'EXTRA_SCHEME': install4jExtraScheme,
2594 'MAC_ICONS_FILE': install4jMacIconsFile,
2595 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2596 'PNG_ICON_FILE': install4jPngIconFile,
2597 'BACKGROUND': install4jBackground,
2601 //println("INSTALL4J VARIABLES:")
2602 //variables.each{k,v->println("${k}=${v}")}
2604 destination = "${jalviewDir}/${install4jBuildDir}"
2605 buildSelected = true
2607 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2609 disableSigning = true
2610 disableNotarization = true
2614 macKeystorePassword = OSX_KEYPASS
2617 if (OSX_ALTOOLPASS) {
2618 appleIdPassword = OSX_ALTOOLPASS
2619 disableNotarization = false
2621 disableNotarization = true
2625 println("Using projectFile "+projectFile)
2626 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2630 inputs.dir(getdownAppBaseDir)
2631 inputs.file(install4jConfFile)
2632 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2633 inputs.dir(macosJavaVMDir)
2634 inputs.dir(windowsJavaVMDir)
2635 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2638 def getDataHash(File myFile) {
2639 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2640 return myFile.exists()
2642 "file" : myFile.getName(),
2643 "filesize" : myFile.length(),
2644 "sha256" : hash.toString()
2649 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2651 "channel" : getdownChannelName,
2652 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2653 "git-commit" : "${gitHash} [${gitBranch}]",
2654 "version" : JALVIEW_VERSION
2656 // install4j installer files
2657 if (installersOutputTxt.exists()) {
2659 installersOutputTxt.readLines().each { def line ->
2660 if (line.startsWith("#")) {
2663 line.replaceAll("\n","")
2664 def vals = line.split("\t")
2665 def filename = vals[3]
2666 def filesize = file(filename).length()
2667 filename = filename.replaceAll(/^.*\//, "")
2668 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2669 idHash."${filename}" = vals[0]
2671 if (install4jCheckSums && installersSha256.exists()) {
2672 installersSha256.readLines().each { def line ->
2673 if (line.startsWith("#")) {
2676 line.replaceAll("\n","")
2677 def vals = line.split(/\s+\*?/)
2678 def filename = vals[1]
2679 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2685 "JAR": shadowJar.archiveFile, // executable JAR
2686 "JVL": getdownVersionLaunchJvl, // version JVL
2687 "SOURCE": sourceDist.archiveFile // source TGZ
2688 ].each { key, value ->
2689 def file = file(value)
2690 if (file.exists()) {
2691 def fileHash = getDataHash(file)
2692 if (fileHash != null) {
2693 hash."${key}" = fileHash;
2697 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2700 task staticMakeInstallersJsonFile {
2702 def output = findProperty("i4j_output")
2703 def sha256 = findProperty("i4j_sha256")
2704 def json = findProperty("i4j_json")
2705 if (output == null || sha256 == null || json == null) {
2706 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2708 writeDataJsonFile(file(output), file(sha256), file(json))
2713 dependsOn installerFiles
2718 eclipse().configFile(eclipse_codestyle_file)
2722 task createSourceReleaseProperties(type: WriteProperties) {
2723 group = "distribution"
2724 description = "Create the source RELEASE properties file"
2726 def sourceTarBuildDir = "${buildDir}/sourceTar"
2727 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2728 outputFile (sourceReleasePropertiesFile)
2731 releaseProps.each{ key, val -> property key, val }
2732 property "git.branch", gitBranch
2733 property "git.hash", gitHash
2736 outputs.file(outputFile)
2739 task sourceDist(type: Tar) {
2740 group "distribution"
2741 description "Create a source .tar.gz file for distribution"
2743 dependsOn createBuildProperties
2744 dependsOn convertMdFiles
2745 dependsOn eclipseAllPreferences
2746 dependsOn createSourceReleaseProperties
2749 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2750 archiveFileName = outputFileName
2752 compression Compression.GZIP
2767 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2769 "utils/InstallAnywhere",
2784 "gradle.properties",
2796 ".settings/org.eclipse.buildship.core.prefs",
2797 ".settings/org.eclipse.jdt.core.prefs"
2801 exclude (EXCLUDE_FILES)
2802 include (PROCESS_FILES)
2803 filter(ReplaceTokens,
2807 'Version-Rel': JALVIEW_VERSION,
2808 'Year-Rel': getDate("yyyy")
2813 exclude (EXCLUDE_FILES)
2814 exclude (PROCESS_FILES)
2815 exclude ("appletlib")
2816 exclude ("**/*locales")
2817 exclude ("*locales/**")
2818 exclude ("utils/InstallAnywhere")
2820 exclude (getdown_files_dir)
2821 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2822 //exclude (getdown_website_dir)
2823 //exclude (getdown_archive_dir)
2825 // exluding these as not using jars as modules yet
2826 exclude ("${j11modDir}/**/*.jar")
2829 include(INCLUDE_FILES)
2831 // from (jalviewDir) {
2832 // // explicit includes for stuff that seemed to not get included
2833 // include(fileTree("test/**/*."))
2834 // exclude(EXCLUDE_FILES)
2835 // exclude(PROCESS_FILES)
2838 from(file(buildProperties).getParent()) {
2839 include(file(buildProperties).getName())
2840 rename(file(buildProperties).getName(), "build_properties")
2842 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2846 def sourceTarBuildDir = "${buildDir}/sourceTar"
2847 from(sourceTarBuildDir) {
2848 // this includes the appended RELEASE properties file
2852 task dataInstallersJson {
2854 description "Create the installers-VERSION.json data file for installer files created"
2856 mustRunAfter installers
2857 mustRunAfter shadowJar
2858 mustRunAfter sourceDist
2859 mustRunAfter getdownArchive
2861 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2862 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2864 if (installersOutputTxt.exists()) {
2865 inputs.file(installersOutputTxt)
2867 if (install4jCheckSums && installersSha256.exists()) {
2868 inputs.file(installersSha256)
2871 shadowJar.archiveFile, // executable JAR
2872 getdownVersionLaunchJvl, // version JVL
2873 sourceDist.archiveFile // source TGZ
2874 ].each { fileName ->
2875 if (file(fileName).exists()) {
2876 inputs.file(fileName)
2880 outputs.file(hugoDataJsonFile)
2883 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2889 description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'."
2891 dependsOn pubhtmlhelp
2893 inputs.dir("${helpBuildDir}/${help_dir}")
2894 outputs.dir("${buildDir}/distributions/${help_dir}")
2898 task j2sSetHeadlessBuild {
2905 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2907 description "Enable the alternative J2S Config file for headless build"
2909 outputFile = jalviewjsJ2sSettingsFileName
2910 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2911 def j2sProps = new Properties()
2912 if (j2sPropsFile.exists()) {
2914 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2915 j2sProps.load(j2sPropsFileFIS)
2916 j2sPropsFileFIS.close()
2918 j2sProps.each { prop, val ->
2921 } catch (Exception e) {
2922 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2926 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2927 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2932 task jalviewjsSetEclipseWorkspace {
2933 def propKey = "jalviewjs_eclipse_workspace"
2935 if (project.hasProperty(propKey)) {
2936 propVal = project.getProperty(propKey)
2937 if (propVal.startsWith("~/")) {
2938 propVal = System.getProperty("user.home") + propVal.substring(1)
2941 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2942 def propsFile = file(propsFileName)
2943 def eclipseWsDir = propVal
2944 def props = new Properties()
2946 def writeProps = true
2947 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2948 def ins = new FileInputStream(propsFileName)
2951 if (props.getProperty(propKey, null) != null) {
2952 eclipseWsDir = props.getProperty(propKey)
2957 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2958 def tempDir = File.createTempDir()
2959 eclipseWsDir = tempDir.getAbsolutePath()
2962 eclipseWorkspace = file(eclipseWsDir)
2965 // do not run a headless transpile when we claim to be in Eclipse
2967 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2968 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2970 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2974 props.setProperty(propKey, eclipseWsDir)
2975 propsFile.parentFile.mkdirs()
2976 def bytes = new ByteArrayOutputStream()
2977 props.store(bytes, null)
2978 def propertiesString = bytes.toString()
2979 propsFile.text = propertiesString
2985 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2988 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2989 outputs.file(propsFileName)
2990 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2994 task jalviewjsEclipsePaths {
2997 def eclipseRoot = jalviewjs_eclipse_root
2998 if (eclipseRoot.startsWith("~/")) {
2999 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
3001 if (OperatingSystem.current().isMacOsX()) {
3002 eclipseRoot += "/Eclipse.app"
3003 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
3004 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
3005 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
3006 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
3007 eclipseRoot += "/eclipse"
3009 eclipseBinary = "${eclipseRoot}/eclipse.exe"
3010 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
3011 } else { // linux or unix
3012 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
3013 eclipseRoot += "/eclipse"
3014 println("eclipseDir exists")
3016 eclipseBinary = "${eclipseRoot}/eclipse"
3017 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
3020 eclipseVersion = "4.13" // default
3021 def assumedVersion = true
3022 if (file(eclipseProduct).exists()) {
3023 def fis = new FileInputStream(eclipseProduct)
3024 def props = new Properties()
3026 eclipseVersion = props.getProperty("version")
3028 assumedVersion = false
3031 def propKey = "eclipse_debug"
3032 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
3035 // do not run a headless transpile when we claim to be in Eclipse
3037 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3038 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3040 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3043 if (!assumedVersion) {
3044 println("ECLIPSE VERSION=${eclipseVersion}")
3050 task printProperties {
3052 description "Output to console all System.properties"
3054 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
3060 dependsOn eclipseProject
3061 dependsOn eclipseClasspath
3062 dependsOn eclipseJdt
3066 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
3067 task jalviewjsEclipseCopyDropins(type: Copy) {
3068 dependsOn jalviewjsEclipsePaths
3070 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
3071 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
3072 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
3079 // this eclipse -clean doesn't actually work
3080 task jalviewjsCleanEclipse(type: Exec) {
3081 dependsOn eclipseSetup
3082 dependsOn jalviewjsEclipsePaths
3083 dependsOn jalviewjsEclipseCopyDropins
3085 executable(eclipseBinary)
3086 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
3092 def inputString = """exit
3095 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
3096 standardInput = inputByteStream
3099 /* not really working yet
3100 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
3104 task jalviewjsTransferUnzipSwingJs {
3105 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
3109 from zipTree(file_zip)
3110 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3114 inputs.file file_zip
3115 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3119 task jalviewjsTransferUnzipLib {
3120 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
3123 zipFiles.each { file_zip ->
3125 from zipTree(file_zip)
3126 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3131 inputs.files zipFiles
3132 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3136 task jalviewjsTransferUnzipAllLibs {
3137 dependsOn jalviewjsTransferUnzipSwingJs
3138 dependsOn jalviewjsTransferUnzipLib
3142 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
3144 description "Create the alternative j2s file from the j2s.* properties"
3146 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
3147 def siteDirProperty = "j2s.site.directory"
3148 def setSiteDir = false
3149 jalviewjsJ2sProps.each { prop, val ->
3151 if (prop == siteDirProperty) {
3152 if (!(val.startsWith('/') || val.startsWith("file://") )) {
3153 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3159 if (!setSiteDir) { // default site location, don't override specifically set property
3160 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3163 outputFile = jalviewjsJ2sAltSettingsFileName
3166 inputs.properties(jalviewjsJ2sProps)
3167 outputs.file(jalviewjsJ2sAltSettingsFileName)
3172 task jalviewjsEclipseSetup {
3173 dependsOn jalviewjsEclipseCopyDropins
3174 dependsOn jalviewjsSetEclipseWorkspace
3175 dependsOn jalviewjsCreateJ2sSettings
3179 task jalviewjsSyncAllLibs (type: Sync) {
3180 dependsOn jalviewjsTransferUnzipAllLibs
3181 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3182 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3183 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3187 def outputFiles = []
3188 rename { filename ->
3189 outputFiles += "${outputDir}/${filename}"
3196 // should this be exclude really ?
3197 duplicatesStrategy "INCLUDE"
3199 outputs.files outputFiles
3200 inputs.files inputFiles
3204 task jalviewjsSyncResources (type: Sync) {
3205 dependsOn buildResources
3207 def inputFiles = fileTree(dir: resourcesBuildDir)
3208 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3212 def outputFiles = []
3213 rename { filename ->
3214 outputFiles += "${outputDir}/${filename}"
3220 outputs.files outputFiles
3221 inputs.files inputFiles
3225 task jalviewjsSyncSiteResources (type: Sync) {
3226 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3227 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3231 def outputFiles = []
3232 rename { filename ->
3233 outputFiles += "${outputDir}/${filename}"
3239 outputs.files outputFiles
3240 inputs.files inputFiles
3244 task jalviewjsSyncBuildProperties (type: Sync) {
3245 dependsOn createBuildProperties
3246 def inputFiles = [file(buildProperties)]
3247 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3251 def outputFiles = []
3252 rename { filename ->
3253 outputFiles += "${outputDir}/${filename}"
3259 outputs.files outputFiles
3260 inputs.files inputFiles
3264 task jalviewjsProjectImport(type: Exec) {
3265 dependsOn eclipseSetup
3266 dependsOn jalviewjsEclipsePaths
3267 dependsOn jalviewjsEclipseSetup
3270 // do not run a headless import when we claim to be in Eclipse
3272 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3273 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3275 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3279 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3280 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3281 executable(eclipseBinary)
3282 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3286 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3288 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3289 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3292 inputs.file("${jalviewDir}/.project")
3293 outputs.upToDateWhen {
3294 file(projdir).exists()
3299 task jalviewjsTranspile(type: Exec) {
3300 dependsOn jalviewjsEclipseSetup
3301 dependsOn jalviewjsProjectImport
3302 dependsOn jalviewjsEclipsePaths
3304 dependsOn jalviewjsEnableAltFileProperty
3308 // do not run a headless transpile when we claim to be in Eclipse
3310 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3311 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3313 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3317 executable(eclipseBinary)
3318 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3322 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3324 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3325 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3331 stdout = new ByteArrayOutputStream()
3332 stderr = new ByteArrayOutputStream()
3334 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3335 def logOutFile = file(logOutFileName)
3336 logOutFile.createNewFile()
3337 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3338 BINARY: ${eclipseBinary}
3339 VERSION: ${eclipseVersion}
3340 WORKSPACE: ${eclipseWorkspace}
3341 DEBUG: ${eclipseDebug}
3344 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3345 // combine stdout and stderr
3346 def logErrFOS = logOutFOS
3348 if (jalviewjs_j2s_to_console.equals("true")) {
3349 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3350 new org.apache.tools.ant.util.TeeOutputStream(
3354 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3355 new org.apache.tools.ant.util.TeeOutputStream(
3360 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3363 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3370 if (stdout.toString().contains("Error processing ")) {
3371 // j2s did not complete transpile
3372 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3373 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3374 println("IGNORING TRANSPILE ERRORS")
3375 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3377 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3382 inputs.dir("${jalviewDir}/${sourceDir}")
3383 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3384 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3388 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3390 def stdout = new ByteArrayOutputStream()
3391 def stderr = new ByteArrayOutputStream()
3393 def coreFile = file(jsfile)
3395 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3397 logOutFile.createNewFile()
3398 logOutFile.append(msg+"\n")
3400 def coreTop = file(prefixFile)
3401 def coreBottom = file(suffixFile)
3402 coreFile.getParentFile().mkdirs()
3403 coreFile.createNewFile()
3404 coreFile.write( coreTop.getText("UTF-8") )
3408 def t = f.getText("UTF-8")
3409 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3410 coreFile.append( t )
3412 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3414 logOutFile.append(msg+"\n")
3417 coreFile.append( coreBottom.getText("UTF-8") )
3419 msg = "Generating ${zjsfile}"
3421 logOutFile.append(msg+"\n")
3422 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3423 def logErrFOS = logOutFOS
3426 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3427 main = "com.google.javascript.jscomp.CommandLineRunner"
3428 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3429 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3432 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3434 logOutFile.append(msg+"\n")
3436 if (logOutConsole) {
3437 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3438 new org.apache.tools.ant.util.TeeOutputStream(
3442 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3443 new org.apache.tools.ant.util.TeeOutputStream(
3448 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3451 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3458 logOutFile.append(msg+"\n")
3462 task jalviewjsBuildAllCores {
3464 description "Build the core js lib closures listed in the classlists dir"
3465 dependsOn jalviewjsTranspile
3466 dependsOn jalviewjsTransferUnzipSwingJs
3468 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3469 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3470 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3471 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3472 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3473 def prefixFile = "${jsDir}/core/coretop2.js"
3474 def suffixFile = "${jsDir}/core/corebottom2.js"
3476 inputs.file prefixFile
3477 inputs.file suffixFile
3479 def classlistFiles = []
3480 // add the classlists found int the jalviewjs_classlists_dir
3481 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3483 def name = file.getName() - ".txt"
3490 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3491 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3492 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3494 jalviewjsCoreClasslists = []
3496 classlistFiles.each {
3499 def file = hash['file']
3500 if (! file.exists()) {
3501 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3502 return false // this is a "continue" in groovy .each closure
3504 def name = hash['name']
3506 name = file.getName() - ".txt"
3514 def list = fileTree(dir: j2sDir, includes: filelist)
3516 def jsfile = "${outputDir}/core${name}.js"
3517 def zjsfile = "${outputDir}/core${name}.z.js"
3519 jalviewjsCoreClasslists += [
3528 outputs.file(jsfile)
3529 outputs.file(zjsfile)
3532 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3533 def stevesoftClasslistName = "_stevesoft"
3534 def stevesoftClasslist = [
3535 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3536 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3537 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3538 'name': stevesoftClasslistName
3540 jalviewjsCoreClasslists += stevesoftClasslist
3541 inputs.files(stevesoftClasslist['list'])
3542 outputs.file(stevesoftClasslist['jsfile'])
3543 outputs.file(stevesoftClasslist['zjsfile'])
3546 def allClasslistName = "_all"
3547 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3548 allJsFiles += fileTree(
3552 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3553 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3554 "**/org/jmol/export/JSExporter.js"
3557 allJsFiles += fileTree(
3561 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3562 "**/sun/misc/Unsafe.js",
3563 "**/swingjs/jquery/jquery-editable-select.js",
3564 "**/swingjs/jquery/j2sComboBox.js",
3565 "**/sun/misc/FloatingDecimal.js"
3568 def allClasslist = [
3569 'jsfile': "${outputDir}/core${allClasslistName}.js",
3570 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3572 'name': allClasslistName
3574 // not including this version of "all" core at the moment
3575 //jalviewjsCoreClasslists += allClasslist
3576 inputs.files(allClasslist['list'])
3577 outputs.file(allClasslist['jsfile'])
3578 outputs.file(allClasslist['zjsfile'])
3581 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3582 logOutFile.getParentFile().mkdirs()
3583 logOutFile.createNewFile()
3584 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3586 jalviewjsCoreClasslists.each {
3587 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3594 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3597 into file(outputFile).getParentFile()
3598 rename { filename ->
3599 if (filename.equals(inputFile.getName())) {
3600 return file(outputFile).getName()
3604 filter(ReplaceTokens,
3608 'MAIN': '"'+main_class+'"',
3610 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3611 'COREKEY': jalviewjs_core_key,
3612 'CORENAME': coreName
3619 task jalviewjsPublishCoreTemplates {
3620 dependsOn jalviewjsBuildAllCores
3621 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3622 def inputFile = file(inputFileName)
3623 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3625 def outputFiles = []
3626 jalviewjsCoreClasslists.each { cl ->
3627 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3628 cl['outputfile'] = outputFile
3629 outputFiles += outputFile
3633 jalviewjsCoreClasslists.each { cl ->
3634 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3637 inputs.file(inputFile)
3638 outputs.files(outputFiles)
3642 task jalviewjsSyncCore (type: Sync) {
3643 dependsOn jalviewjsBuildAllCores
3644 dependsOn jalviewjsPublishCoreTemplates
3645 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3646 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3650 def outputFiles = []
3651 rename { filename ->
3652 outputFiles += "${outputDir}/${filename}"
3658 outputs.files outputFiles
3659 inputs.files inputFiles
3663 // this Copy version of TransferSiteJs will delete anything else in the target dir
3664 task jalviewjsCopyTransferSiteJs(type: Copy) {
3665 dependsOn jalviewjsTranspile
3666 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3667 into "${jalviewDir}/${jalviewjsSiteDir}"
3671 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3672 task jalviewjsSyncTransferSiteJs(type: Sync) {
3673 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3675 into "${jalviewDir}/${jalviewjsSiteDir}"
3682 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3683 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3684 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3685 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3687 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3688 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3689 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3690 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3693 task jalviewjsPrepareSite {
3695 description "Prepares the website folder including unzipping files and copying resources"
3696 dependsOn jalviewjsSyncAllLibs
3697 dependsOn jalviewjsSyncResources
3698 dependsOn jalviewjsSyncSiteResources
3699 dependsOn jalviewjsSyncBuildProperties
3700 dependsOn jalviewjsSyncCore
3704 task jalviewjsBuildSite {
3706 description "Builds the whole website including transpiled code"
3707 dependsOn jalviewjsCopyTransferSiteJs
3708 dependsOn jalviewjsPrepareSite
3712 task cleanJalviewjsTransferSite {
3714 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3715 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3716 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3717 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3722 task cleanJalviewjsSite {
3723 dependsOn cleanJalviewjsTransferSite
3725 delete "${jalviewDir}/${jalviewjsSiteDir}"
3730 task jalviewjsSiteTar(type: Tar) {
3732 description "Creates a tar.gz file for the website"
3733 dependsOn jalviewjsBuildSite
3734 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3735 archiveFileName = outputFilename
3737 compression Compression.GZIP
3739 from "${jalviewDir}/${jalviewjsSiteDir}"
3740 into jalviewjs_site_dir // this is inside the tar file
3742 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3746 task jalviewjsServer {
3748 def filename = "jalviewjsTest.html"
3749 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3750 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3755 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3756 factory = f.newInstance()
3757 } catch (ClassNotFoundException e) {
3758 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3760 def port = Integer.valueOf(jalviewjs_server_port)
3765 while(port < start+1000 && !running) {
3767 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3768 jalviewjsServer = factory.start(doc_root, port)
3770 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3771 println("SERVER STARTED with document root ${doc_root}.")
3772 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3773 println("For debug: "+url+"?j2sdebug")
3774 println("For verbose: "+url+"?j2sverbose")
3775 } catch (Exception e) {
3780 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3781 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3782 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3784 jalviewjsCoreClasslists.each { cl ->
3785 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3787 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3789 println("For core ${cl.name}: "+urlcore)
3792 file(htmlFile).text = htmlText
3795 outputs.file(htmlFile)
3796 outputs.upToDateWhen({false})
3800 task cleanJalviewjsAll {
3802 description "Delete all configuration and build artifacts to do with JalviewJS build"
3803 dependsOn cleanJalviewjsSite
3804 dependsOn jalviewjsEclipsePaths
3807 delete "${jalviewDir}/${jalviewjsBuildDir}"
3808 delete "${jalviewDir}/${eclipse_bin_dir}"
3809 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3810 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3812 delete jalviewjsJ2sAltSettingsFileName
3815 outputs.upToDateWhen( { false } )
3819 task jalviewjsIDE_checkJ2sPlugin {
3820 group "00 JalviewJS in Eclipse"
3821 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3824 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3825 def j2sPluginFile = file(j2sPlugin)
3826 def eclipseHome = System.properties["eclipse.home.location"]
3827 if (eclipseHome == null || ! IN_ECLIPSE) {
3828 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3830 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3831 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3832 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3833 eclipseJ2sPluginDirs += altPluginsDir
3835 def foundPlugin = false
3836 def j2sPluginFileName = j2sPluginFile.getName()
3837 def eclipseJ2sPlugin
3838 def eclipseJ2sPluginFile
3839 eclipseJ2sPluginDirs.any { dir ->
3840 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3841 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3842 if (eclipseJ2sPluginFile.exists()) {
3848 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3849 System.err.println(msg)
3850 throw new StopExecutionException(msg)
3853 def digest = MessageDigest.getInstance("MD5")
3855 digest.update(j2sPluginFile.text.bytes)
3856 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3858 digest.update(eclipseJ2sPluginFile.text.bytes)
3859 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3861 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3862 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3863 System.err.println(msg)
3864 throw new StopExecutionException(msg)
3866 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3872 task jalviewjsIDE_copyJ2sPlugin {
3873 group "00 JalviewJS in Eclipse"
3874 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3877 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3878 def j2sPluginFile = file(j2sPlugin)
3879 def eclipseHome = System.properties["eclipse.home.location"]
3880 if (eclipseHome == null || ! IN_ECLIPSE) {
3881 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3883 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3884 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3885 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3886 System.err.println(msg)
3889 eclipseJ2sPluginFile.getParentFile().mkdirs()
3890 into eclipseJ2sPluginFile.getParent()
3896 task jalviewjsIDE_j2sFile {
3897 group "00 JalviewJS in Eclipse"
3898 description "Creates the .j2s file"
3899 dependsOn jalviewjsCreateJ2sSettings
3903 task jalviewjsIDE_SyncCore {
3904 group "00 JalviewJS in Eclipse"
3905 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3906 dependsOn jalviewjsSyncCore
3910 task jalviewjsIDE_SyncSiteAll {
3911 dependsOn jalviewjsSyncAllLibs
3912 dependsOn jalviewjsSyncResources
3913 dependsOn jalviewjsSyncSiteResources
3914 dependsOn jalviewjsSyncBuildProperties
3918 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3921 task jalviewjsIDE_PrepareSite {
3922 group "00 JalviewJS in Eclipse"
3923 description "Sync libs and resources to site dir, but not closure cores"
3925 dependsOn jalviewjsIDE_SyncSiteAll
3926 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3930 task jalviewjsIDE_AssembleSite {
3931 group "00 JalviewJS in Eclipse"
3932 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3933 dependsOn jalviewjsPrepareSite
3937 task jalviewjsIDE_SiteClean {
3938 group "00 JalviewJS in Eclipse"
3939 description "Deletes the Eclipse transpiled site"
3940 dependsOn cleanJalviewjsSite
3944 task jalviewjsIDE_Server {
3945 group "00 JalviewJS in Eclipse"
3946 description "Starts a webserver on localhost to test the website"
3947 dependsOn jalviewjsServer
3951 // buildship runs this at import or gradle refresh
3952 task eclipseSynchronizationTask {
3953 //dependsOn eclipseSetup
3954 dependsOn createBuildProperties
3956 dependsOn jalviewjsIDE_j2sFile
3957 dependsOn jalviewjsIDE_checkJ2sPlugin
3958 dependsOn jalviewjsIDE_PrepareSite
3963 // buildship runs this at build time or project refresh
3964 task eclipseAutoBuildTask {
3965 //dependsOn jalviewjsIDE_checkJ2sPlugin
3966 //dependsOn jalviewjsIDE_PrepareSite
3972 description "Build the site"
3973 dependsOn jalviewjsBuildSite