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"
49 id "com.diffplug.gradle.spotless" version "3.28.0"
50 id 'com.github.johnrengelman.shadow' version '4.0.3'
51 id 'com.install4j.gradle' version '9.0.6'
52 id 'com.dorongold.task-tree' version '2.1.0' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
53 id 'com.palantir.git-version' version '0.13.0' apply false
64 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
65 def string(Object o) {
66 return o == null ? "" : o.toString()
69 def overrideProperties(String propsFileName, boolean output = false) {
70 if (propsFileName == null) {
73 def propsFile = file(propsFileName)
74 if (propsFile != null && propsFile.exists()) {
75 println("Using properties from file '${propsFileName}'")
77 def p = new Properties()
78 def localPropsFIS = new FileInputStream(propsFile)
84 if (project.hasProperty(key)) {
85 oldval = project.findProperty(key)
86 project.setProperty(key, val)
88 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
91 ext.setProperty(key, val)
93 println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'")
97 } catch (Exception e) {
98 println("Exception reading local.properties")
105 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
106 jalviewDirRelativePath = jalviewDir
109 getdownChannelName = CHANNEL.toLowerCase()
110 // default to "default". Currently only has different cosmetics for "develop", "release", "default"
111 propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default"
112 channelDirName = propertiesChannelName
113 // Import channel_properties
114 if (getdownChannelName.startsWith("develop-")) {
115 channelDirName = "develop-SUFFIX"
116 println("SET propertiesChannelName to '${propertiesChannelName}'")
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 getdownChannelDir = string("${getdown_website_dir}/${propertiesChannelName}")
209 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
210 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
211 getdownFullArchiveDir = null
212 getdownTextLines = []
213 getdownLaunchJvl = null
214 getdownVersionLaunchJvl = null
216 buildProperties = null
218 // the following values might be overridden by the CHANNEL switch
219 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
220 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
221 getdownArchiveAppBase = getdown_archive_base
222 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
223 getdownAppDistDir = getdown_app_dir_alt
224 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
225 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
226 reportRsyncCommand = false
227 jvlChannelName = CHANNEL.toLowerCase()
228 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
229 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
230 install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}"
231 install4jInstallerName = "${jalview_name} Non-Release Installer"
232 install4jExecutableName = install4j_executable_name
233 install4jExtraScheme = "jalviewx"
234 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
235 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
236 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
237 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
238 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
239 install4jCheckSums = true
241 applicationName = "${jalview_name}"
245 // TODO: get bamboo build artifact URL for getdown artifacts
246 getdown_channel_base = bamboo_channelbase
247 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
248 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
249 jvlChannelName += "_${getdownChannelName}"
250 // automatically add the test group Not-bamboo for exclusion
251 if ("".equals(testng_excluded_groups)) {
252 testng_excluded_groups = "Not-bamboo"
254 install4jExtraScheme = "jalviewb"
257 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
258 getdownAppDistDir = getdown_app_dir_release
259 getdownSetAppBaseProperty = true
260 reportRsyncCommand = true
262 install4jInstallerName = "${jalview_name} Installer"
266 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
267 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
268 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
269 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
270 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
272 package_dir = string("${ARCHIVEDIR}/${package_dir}")
273 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
276 reportRsyncCommand = true
277 install4jExtraScheme = "jalviewa"
281 getdownChannelName = string("archive/${JALVIEW_VERSION}")
282 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
283 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
284 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
285 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
287 package_dir = string("${ARCHIVEDIR}/${package_dir}")
288 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
291 reportRsyncCommand = true
292 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
293 install4jSuffix = "Archive"
294 install4jExtraScheme = "jalviewa"
297 case ~/^DEVELOP-([\.\-\w]*)$/:
298 def suffix = Matcher.lastMatcher[0][1]
299 reportRsyncCommand = true
300 getdownSetAppBaseProperty = true
301 JALVIEW_VERSION=JALVIEW_VERSION+"-d${suffix}-${buildDate}"
302 install4jSuffix = "Develop ${suffix}"
303 install4jExtraScheme = "jalviewd"
304 install4jInstallerName = "${jalview_name} Develop ${suffix} Installer"
305 getdownChannelName = string("develop-${suffix}")
306 getdownChannelDir = string("${getdown_website_dir}/${getdownChannelName}")
307 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
308 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
309 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
310 channelSuffix = string(suffix)
314 reportRsyncCommand = true
315 getdownSetAppBaseProperty = true
316 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
317 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
319 install4jSuffix = "Develop"
320 install4jExtraScheme = "jalviewd"
321 install4jInstallerName = "${jalview_name} Develop Installer"
325 reportRsyncCommand = true
326 getdownSetAppBaseProperty = true
327 // Don't ignore transpile errors for release build
328 if (jalviewjs_ignore_transpile_errors.equals("true")) {
329 jalviewjs_ignore_transpile_errors = "false"
330 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
332 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
333 install4jSuffix = "Test"
334 install4jExtraScheme = "jalviewt"
335 install4jInstallerName = "${jalview_name} Test Installer"
338 case ~/^SCRATCH(|-[-\w]*)$/:
339 getdownChannelName = CHANNEL
340 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
342 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
343 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
344 reportRsyncCommand = true
345 install4jSuffix = "Scratch"
349 if (!file("${LOCALDIR}").exists()) {
350 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
352 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
353 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
355 JALVIEW_VERSION = "TEST"
356 install4jSuffix = "Test-Local"
357 install4jExtraScheme = "jalviewt"
358 install4jInstallerName = "${jalview_name} Test Installer"
361 case [ "LOCAL", "JALVIEWJS" ]:
362 JALVIEW_VERSION = "TEST"
363 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
364 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
365 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
366 install4jExtraScheme = "jalviewl"
367 install4jCheckSums = false
370 default: // something wrong specified
371 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
375 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
376 hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_data_installers_dir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
377 hugoArchiveMdFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_version_archive_dir}/Version-${JALVIEW_VERSION_UNDERSCORES}/_index.md")
378 // override getdownAppBase if requested
379 if (findProperty("getdown_appbase_override") != null) {
380 // revert to LOCAL if empty string
381 if (string(getdown_appbase_override) == "") {
382 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
383 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
384 } else if (string(getdown_appbase_override).startsWith("file://")) {
385 getdownAppBase = string(getdown_appbase_override)
386 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
388 getdownAppBase = string(getdown_appbase_override)
390 println("Overriding getdown appbase with '${getdownAppBase}'")
392 // sanitise file name for jalview launcher file for this channel
393 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
394 // install4j application and folder names
395 if (install4jSuffix == "") {
396 install4jBundleId = "${install4j_bundle_id}"
397 install4jWinApplicationId = install4j_release_win_application_id
399 applicationName = "${jalview_name} ${install4jSuffix}"
400 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
401 // add int hash of install4jSuffix to the last part of the application_id
402 def id = install4j_release_win_application_id
403 def idsplitreverse = id.split("-").reverse()
404 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
405 install4jWinApplicationId = idsplitreverse.reverse().join("-")
407 // sanitise folder and id names
408 // install4jApplicationFolder = e.g. "Jalview Build"
409 install4jApplicationFolder = applicationName
410 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
411 .replaceAll("_+", "_") // collapse __
412 install4jInternalId = applicationName
414 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
415 .replaceAll("_+", "") // collapse __
416 //.replaceAll("_*-_*", "-") // collapse _-_
417 install4jUnixApplicationFolder = applicationName
419 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
420 .replaceAll("_+", "_") // collapse __
421 .replaceAll("_*-_*", "-") // collapse _-_
424 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
425 getdownAppDir = string("${getdownAppBaseDir}/${getdownAppDistDir}")
426 //getdownJ11libDir = "${getdownAppBaseDir}/${getdown_j11lib_dir}"
427 getdownResourceDir = string("${getdownAppBaseDir}/${getdown_resource_dir}")
428 getdownInstallDir = string("${getdownAppBaseDir}/${getdown_install_dir}")
429 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
430 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
431 /* compile without modules -- using classpath libraries
432 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
433 modules_runtimeClasspath = modules_compileClasspath
439 apply plugin: "com.palantir.git-version"
440 def details = versionDetails()
441 gitHash = details.gitHash
442 gitBranch = details.branchName
443 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
444 println("Not in a git repository. Using git values from RELEASE properties file.")
445 gitHash = releaseProps.getProperty("git.hash")
446 gitBranch = releaseProps.getProperty("git.branch")
447 } catch(java.lang.RuntimeException e1) {
448 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
451 println("Using a ${CHANNEL} profile.")
453 additional_compiler_args = []
454 // configure classpath/args for j8/j11 compilation
455 if (JAVA_VERSION.equals("1.8")) {
456 JAVA_INTEGER_VERSION = string("8")
459 libDistDir = j8libDir
460 compile_source_compatibility = 1.8
461 compile_target_compatibility = 1.8
462 // these are getdown.txt properties defined dependent on the JAVA_VERSION
463 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
464 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
465 // this property is assigned below and expanded to multiple lines in the getdown task
466 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
467 // this property is for the Java library used in eclipse
468 eclipseJavaRuntimeName = string("JavaSE-1.8")
469 } else if (JAVA_VERSION.equals("11")) {
470 JAVA_INTEGER_VERSION = string("11")
472 libDistDir = j11libDir
473 compile_source_compatibility = 11
474 compile_target_compatibility = 11
475 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
476 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
477 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
478 eclipseJavaRuntimeName = string("JavaSE-11")
479 /* compile without modules -- using classpath libraries
480 additional_compiler_args += [
481 '--module-path', modules_compileClasspath.asPath,
482 '--add-modules', j11modules
485 } else if (JAVA_VERSION.equals("17")) {
486 JAVA_INTEGER_VERSION = string("17")
488 libDistDir = j17libDir
489 compile_source_compatibility = 17
490 compile_target_compatibility = 17
491 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
492 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
493 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
494 eclipseJavaRuntimeName = string("JavaSE-17")
495 /* compile without modules -- using classpath libraries
496 additional_compiler_args += [
497 '--module-path', modules_compileClasspath.asPath,
498 '--add-modules', j11modules
502 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
507 JAVA_MIN_VERSION = JAVA_VERSION
508 JAVA_MAX_VERSION = JAVA_VERSION
509 def jreInstallsDir = string(jre_installs_dir)
510 if (jreInstallsDir.startsWith("~/")) {
511 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
513 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
514 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
515 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
516 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
517 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
518 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
519 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
520 install4jConfFileName = string("jalview-install4j-conf.install4j")
521 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
522 install4jHomeDir = install4j_home_dir
523 if (install4jHomeDir.startsWith("~/")) {
524 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
527 resourceBuildDir = string("${buildDir}/resources")
528 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
529 helpBuildDir = string("${resourceBuildDir}/help_build")
530 docBuildDir = string("${resourceBuildDir}/doc_build")
532 if (buildProperties == null) {
533 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
535 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
536 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
537 helpSourceDir = string("${helpParentDir}/${help_dir}")
538 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
541 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
542 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
543 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
545 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
547 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
549 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
550 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
551 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
552 jalviewjsJalviewCoreHtmlFile = string("")
553 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
554 jalviewjsCoreClasslists = []
555 jalviewjsJalviewTemplateName = string(jalviewjs_name)
556 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
557 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
558 jalviewjsJ2sProps = null
559 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
561 eclipseWorkspace = null
562 eclipseBinary = string("")
563 eclipseVersion = string("")
573 outputDir = file(classesDir)
577 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
580 compileClasspath = files(sourceSets.main.java.outputDir)
581 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
583 runtimeClasspath = compileClasspath
584 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
589 srcDirs cloverInstrDir
590 outputDir = cloverClassesDir
594 srcDirs = sourceSets.main.resources.srcDirs
597 compileClasspath = files( sourceSets.clover.java.outputDir )
598 //compileClasspath += files( testClassesDir )
599 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
600 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
601 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
603 runtimeClasspath = compileClasspath
608 srcDirs testSourceDir
609 outputDir = file(testClassesDir)
613 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
616 compileClasspath = files( sourceSets.test.java.outputDir )
617 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
618 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
620 runtimeClasspath = compileClasspath
621 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
627 // eclipse project and settings files creation, also used by buildship
630 name = eclipse_project_name
632 natures 'org.eclipse.jdt.core.javanature',
633 'org.eclipse.jdt.groovy.core.groovyNature',
634 'org.eclipse.buildship.core.gradleprojectnature'
636 buildCommand 'org.eclipse.jdt.core.javabuilder'
637 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
641 //defaultOutputDir = sourceSets.main.java.outputDir
642 configurations.each{ c->
643 if (c.isCanBeResolved()) {
644 minusConfigurations += [c]
648 plusConfigurations = [ ]
652 def removeTheseToo = []
653 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
654 cp.entries.each { entry ->
655 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
656 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
657 // we add the resources and help/help dirs in as libs afterwards (see below)
658 if (entry.kind == 'src') {
659 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
660 removeTheseToo += entry
662 alreadyAddedSrcPath.putAt(entry.path, true)
667 cp.entries.removeAll(removeTheseToo)
669 //cp.entries += new Output("${eclipse_bin_dir}/main")
670 if (file(helpParentDir).isDirectory()) {
671 cp.entries += new Library(fileReference(helpParentDir))
673 if (file(resourceDir).isDirectory()) {
674 cp.entries += new Library(fileReference(resourceDir))
677 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
679 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
680 //don't want to add outputDir as eclipse is using its own output dir in bin/main
681 if (it.isDirectory() || ! it.exists()) {
682 // don't add dirs to classpath, especially if they don't exist
683 return false // groovy "continue" in .any closure
685 def itPath = it.toString()
686 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
687 // make relative path
688 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
690 if (alreadyAddedLibPath.get(itPath)) {
691 //println("Not adding duplicate entry "+itPath)
693 //println("Adding entry "+itPath)
694 cp.entries += new Library(fileReference(itPath))
695 alreadyAddedLibPath.put(itPath, true)
699 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
700 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
701 if (it.isDirectory() || ! it.exists()) {
702 // don't add dirs to classpath
703 return false // groovy "continue" in .any closure
706 def itPath = it.toString()
707 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
708 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
710 if (alreadyAddedLibPath.get(itPath)) {
713 def lib = new Library(fileReference(itPath))
714 lib.entryAttributes["test"] = "true"
716 alreadyAddedLibPath.put(itPath, true)
724 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
729 // for the IDE, use java 11 compatibility
730 sourceCompatibility = compile_source_compatibility
731 targetCompatibility = compile_target_compatibility
732 javaRuntimeName = eclipseJavaRuntimeName
734 // add in jalview project specific properties/preferences into eclipse core preferences
736 withProperties { props ->
737 def jalview_prefs = new Properties()
738 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
739 jalview_prefs.load(ins)
741 jalview_prefs.forEach { t, v ->
742 if (props.getAt(t) == null) {
746 // codestyle file -- overrides previous formatter prefs
747 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
748 if (csFile.exists()) {
749 XmlParser parser = new XmlParser()
750 def profiles = parser.parse(csFile)
751 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
752 if (profile != null) {
753 profile.'setting'.each { s ->
755 def value = s.'@value'
756 if (id != null && value != null) {
757 props.putAt(id, value)
768 // Don't want these to be activated if in headless build
769 synchronizationTasks "eclipseSynchronizationTask"
770 //autoBuildTasks "eclipseAutoBuildTask"
776 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
777 // Class to allow updating arbitrary properties files
778 class PropertiesFile extends PropertiesPersistableConfigurationObject {
779 public PropertiesFile(PropertiesTransformer t) { super(t); }
780 @Override protected void load(Properties properties) { }
781 @Override protected void store(Properties properties) { }
782 @Override protected String getDefaultResourceName() { return ""; }
783 // This is necessary, because PropertiesPersistableConfigurationObject fails
784 // if no default properties file exists.
785 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
788 // Task to update arbitrary properties files (set outputFile)
789 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
790 private final PropertiesFileContentMerger file;
791 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
792 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
793 protected void configure(PropertiesFile props) {
794 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
796 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
799 task eclipseUIPreferences(type: PropertiesFileTask) {
800 description = "Generate Eclipse additional settings"
801 def filename = "org.eclipse.jdt.ui.prefs"
802 outputFile = "$projectDir/.settings/${filename}" as File
805 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
810 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
811 description = "Generate Eclipse additional settings"
812 def filename = "org.eclipse.jdt.groovy.core.prefs"
813 outputFile = "$projectDir/.settings/${filename}" as File
816 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
821 task eclipseAllPreferences {
823 dependsOn eclipseUIPreferences
824 dependsOn eclipseGroovyCorePreferences
827 eclipseUIPreferences.mustRunAfter eclipseJdt
828 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
830 /* end of eclipse preferences hack */
838 delete cloverBuildDir
839 delete cloverReportDir
844 task cloverInstrJava(type: JavaExec) {
845 group = "Verification"
846 description = "Create clover instrumented source java files"
848 dependsOn cleanClover
850 inputs.files(sourceSets.main.allJava)
851 outputs.dir(cloverInstrDir)
853 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
854 classpath = sourceSets.clover.compileClasspath
855 main = "com.atlassian.clover.CloverInstr"
863 cloverInstrDir.getPath(),
865 def srcFiles = sourceSets.main.allJava.files
868 { file -> file.absolutePath }
871 args argsList.toArray()
874 delete cloverInstrDir
875 println("Clover: About to instrument "+srcFiles.size() +" files")
880 task cloverInstrTests(type: JavaExec) {
881 group = "Verification"
882 description = "Create clover instrumented source test files"
884 dependsOn cleanClover
886 inputs.files(testDir)
887 outputs.dir(cloverTestInstrDir)
889 classpath = sourceSets.clover.compileClasspath
890 main = "com.atlassian.clover.CloverInstr"
900 cloverTestInstrDir.getPath(),
902 args argsList.toArray()
905 delete cloverTestInstrDir
906 println("Clover: About to instrument test files")
912 group = "Verification"
913 description = "Create clover instrumented all source files"
915 dependsOn cloverInstrJava
916 dependsOn cloverInstrTests
920 cloverClasses.dependsOn cloverInstr
923 task cloverConsoleReport(type: JavaExec) {
924 group = "Verification"
925 description = "Creates clover console report"
928 file(cloverDb).exists()
931 inputs.dir cloverClassesDir
933 classpath = sourceSets.clover.runtimeClasspath
934 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
936 if (cloverreport_mem.length() > 0) {
937 maxHeapSize = cloverreport_mem
939 if (cloverreport_jvmargs.length() > 0) {
940 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
950 args argsList.toArray()
954 task cloverHtmlReport(type: JavaExec) {
955 group = "Verification"
956 description = "Creates clover HTML report"
959 file(cloverDb).exists()
962 def cloverHtmlDir = cloverReportDir
963 inputs.dir cloverClassesDir
964 outputs.dir cloverHtmlDir
966 classpath = sourceSets.clover.runtimeClasspath
967 main = "com.atlassian.clover.reporters.html.HtmlReporter"
969 if (cloverreport_mem.length() > 0) {
970 maxHeapSize = cloverreport_mem
972 if (cloverreport_jvmargs.length() > 0) {
973 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
984 if (cloverreport_html_options.length() > 0) {
985 argsList += cloverreport_html_options.split(" ")
988 args argsList.toArray()
992 task cloverXmlReport(type: JavaExec) {
993 group = "Verification"
994 description = "Creates clover XML report"
997 file(cloverDb).exists()
1000 def cloverXmlFile = "${cloverReportDir}/clover.xml"
1001 inputs.dir cloverClassesDir
1002 outputs.file cloverXmlFile
1004 classpath = sourceSets.clover.runtimeClasspath
1005 main = "com.atlassian.clover.reporters.xml.XMLReporter"
1007 if (cloverreport_mem.length() > 0) {
1008 maxHeapSize = cloverreport_mem
1010 if (cloverreport_jvmargs.length() > 0) {
1011 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
1022 if (cloverreport_xml_options.length() > 0) {
1023 argsList += cloverreport_xml_options.split(" ")
1026 args argsList.toArray()
1031 group = "Verification"
1032 description = "Creates clover reports"
1034 dependsOn cloverXmlReport
1035 dependsOn cloverHtmlReport
1042 sourceCompatibility = compile_source_compatibility
1043 targetCompatibility = compile_target_compatibility
1044 options.compilerArgs += additional_compiler_args
1045 print ("Setting target compatibility to "+targetCompatibility+"\n")
1047 //classpath += configurations.cloverRuntime
1053 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1054 sourceCompatibility = compile_source_compatibility
1055 targetCompatibility = compile_target_compatibility
1056 options.compilerArgs = additional_compiler_args
1057 options.encoding = "UTF-8"
1059 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1066 sourceCompatibility = compile_source_compatibility
1067 targetCompatibility = compile_target_compatibility
1068 options.compilerArgs = additional_compiler_args
1070 print ("Setting target compatibility to "+targetCompatibility+"\n")
1077 delete sourceSets.main.java.outputDir
1083 dependsOn cleanClover
1085 delete sourceSets.test.java.outputDir
1090 // format is a string like date.format("dd MMMM yyyy")
1091 def getDate(format) {
1092 return date.format(format)
1096 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1097 MutableDataSet options = new MutableDataSet()
1099 def extensions = new ArrayList<>()
1100 extensions.add(AnchorLinkExtension.create())
1101 extensions.add(AutolinkExtension.create())
1102 extensions.add(StrikethroughExtension.create())
1103 extensions.add(TaskListExtension.create())
1104 extensions.add(TablesExtension.create())
1105 extensions.add(TocExtension.create())
1107 options.set(Parser.EXTENSIONS, extensions)
1109 // set GFM table parsing options
1110 options.set(TablesExtension.WITH_CAPTION, false)
1111 options.set(TablesExtension.COLUMN_SPANS, false)
1112 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1113 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1114 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1115 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1116 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1118 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1119 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1120 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1121 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1123 Parser parser = Parser.builder(options).build()
1124 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1126 mdFiles.each { mdFile ->
1127 // add table of contents
1128 def mdText = "[TOC]\n"+mdFile.text
1130 // grab the first top-level title
1132 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1133 def matcher = mdText =~ titleRegex
1134 if (matcher.size() > 0) {
1135 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1136 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1138 // or use the filename if none found
1139 if (title == null) {
1140 title = mdFile.getName()
1143 Node document = parser.parse(mdText)
1144 String htmlBody = renderer.render(document)
1145 def htmlText = '''<html>
1146 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1147 <html xmlns="http://www.w3.org/1999/xhtml">
1149 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1150 <meta http-equiv="Content-Style-Type" content="text/css" />
1151 <meta name="generator" content="flexmark" />
1153 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1155 <style type="text/css">code{white-space: pre;}</style>
1157 htmlText += ((cssFile != null) ? cssFile.text : '')
1158 htmlText += '''</head>
1161 htmlText += htmlBody
1167 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1168 def htmlFile = file(htmlFilePath)
1169 println("Creating ${htmlFilePath}")
1170 htmlFile.text = htmlText
1175 task copyDocs(type: Copy) {
1176 def inputDir = "${jalviewDir}/${doc_dir}"
1177 def outputDir = "${docBuildDir}/${doc_dir}"
1181 include('**/*.html')
1183 filter(ReplaceTokens,
1187 'Version-Rel': JALVIEW_VERSION,
1188 'Year-Rel': getDate("yyyy")
1195 exclude('**/*.html')
1200 inputs.dir(inputDir)
1201 outputs.dir(outputDir)
1205 task convertMdFiles {
1207 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1208 def cssFile = file("${jalviewDir}/${flexmark_css}")
1211 convertMdToHtml(mdFiles, cssFile)
1214 inputs.files(mdFiles)
1215 inputs.file(cssFile)
1218 mdFiles.each { mdFile ->
1219 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1220 htmlFiles.add(file(htmlFilePath))
1222 outputs.files(htmlFiles)
1226 def hugoTemplateSubstitutions(String input, Map extras=null) {
1227 def replacements = [
1228 DATE: getDate("yyyy-MM-dd"),
1229 CHANNEL: propertiesChannelName,
1230 APPLICATION_NAME: applicationName,
1232 GIT_BRANCH: gitBranch,
1233 VERSION: JALVIEW_VERSION,
1234 JAVA_VERSION: JAVA_VERSION,
1235 VERSION_UNDERSCORES: JALVIEW_VERSION_UNDERSCORES,
1240 if (extras != null) {
1241 extras.each{ k, v ->
1242 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1245 replacements.each{ k, v ->
1246 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1251 def mdFileComponents(File mdFile, def dateOnly=false) {
1254 if (mdFile.exists()) {
1255 def inFrontMatter = false
1256 def firstLine = true
1257 mdFile.eachLine { line ->
1258 if (line.matches("---")) {
1259 def prev = inFrontMatter
1260 inFrontMatter = firstLine
1261 if (inFrontMatter != prev)
1264 if (inFrontMatter) {
1266 if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
1267 map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
1268 } else if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
1269 map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
1270 } else if (m = line =~ /^channel:\s*(\S+)/) {
1271 map["channel"] = m[0][1]
1272 } else if (m = line =~ /^version:\s*(\S+)/) {
1273 map["version"] = m[0][1]
1274 } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
1275 map[ m[0][1] ] = m[0][2]
1277 if (dateOnly && map["date"] != null) {
1283 content += line+"\n"
1288 return dateOnly ? map["date"] : [map, content]
1291 task hugoTemplates {
1293 description "Create partially populated md pages for hugo website build"
1295 def hugoTemplatesDir = file("${jalviewDir}/${hugo_templates_dir}")
1296 def hugoBuildDir = "${jalviewDir}/${hugo_build_dir}"
1297 def templateFiles = fileTree(dir: hugoTemplatesDir)
1298 def releaseMdFile = file("${jalviewDir}/${releases_dir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1299 def whatsnewMdFile = file("${jalviewDir}/${whatsnew_dir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1300 def oldJvlFile = file("${jalviewDir}/${hugo_old_jvl}")
1301 def jalviewjsFile = file("${jalviewDir}/${hugo_jalviewjs}")
1304 // specific release template for version archive
1307 def givenDate = null
1308 def givenChannel = null
1309 def givenVersion = null
1310 if (CHANNEL == "RELEASE") {
1311 def (map, content) = mdFileComponents(releaseMdFile)
1312 givenDate = map.date
1313 givenChannel = map.channel
1314 givenVersion = map.version
1316 if (givenVersion != null && givenVersion != JALVIEW_VERSION) {
1317 throw new GradleException("'version' header (${givenVersion}) found in ${releaseMdFile} does not match JALVIEW_VERSION (${JALVIEW_VERSION})")
1320 if (whatsnewMdFile.exists())
1321 whatsnew = whatsnewMdFile.text
1324 def oldJvl = oldJvlFile.exists() ? oldJvlFile.collect{it} : []
1325 def jalviewjsLink = jalviewjsFile.exists() ? jalviewjsFile.collect{it} : []
1327 def changesHugo = null
1328 if (changes != null) {
1329 changesHugo = '<div class="release_notes">\n\n'
1330 def inSection = false
1331 changes.eachLine { line ->
1333 if (m = line =~ /^##([^#].*)$/) {
1335 changesHugo += "</div>\n\n"
1337 def section = m[0][1].trim()
1338 section = section.toLowerCase()
1339 section = section.replaceAll(/ +/, "_")
1340 section = section.replaceAll(/[^a-z0-9_\-]/, "")
1341 changesHugo += "<div class=\"${section}\">\n\n"
1343 } else if (m = line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
1344 def comment = m[0][2].trim()
1345 if (comment != "") {
1346 comment = comment.replaceAll('"', """)
1348 comment.eachMatch(/JAL-\d+/) { jal -> issuekeys += jal }
1349 def newline = m[0][1]
1350 if (comment.trim() != "")
1351 newline += "{{<comment>}}${comment}{{</comment>}} "
1352 newline += m[0][3].trim()
1353 if (issuekeys.size() > 0)
1354 newline += " {{< jal issue=\"${issuekeys.join(",")}\" alt=\"${comment}\" >}}"
1355 if (m[0][4] != null)
1360 changesHugo += line+"\n"
1363 changesHugo += "\n</div>\n\n"
1365 changesHugo += '</div>'
1368 templateFiles.each{ templateFile ->
1369 def newFileName = string(hugoTemplateSubstitutions(templateFile.getName()))
1370 def relPath = hugoTemplatesDir.toPath().relativize(templateFile.toPath()).getParent()
1371 def newRelPathName = hugoTemplateSubstitutions( relPath.toString() )
1373 def outPathName = string("${hugoBuildDir}/$newRelPathName")
1377 rename(templateFile.getName(), newFileName)
1381 def newFile = file("${outPathName}/${newFileName}".toString())
1382 def content = newFile.text
1383 newFile.text = hugoTemplateSubstitutions(content,
1386 CHANGES: changesHugo,
1387 DATE: givenDate == null ? "" : givenDate.format("yyyy-MM-dd"),
1388 DRAFT: givenDate == null ? "true" : "false",
1389 JALVIEWJSLINK: jalviewjsLink.contains(JALVIEW_VERSION) ? "true" : "false",
1390 JVL_HEADER: oldJvl.contains(JALVIEW_VERSION) ? "jvl: true" : ""
1397 inputs.file(oldJvlFile)
1398 inputs.dir(hugoTemplatesDir)
1399 inputs.property("JALVIEW_VERSION", { JALVIEW_VERSION })
1400 inputs.property("CHANNEL", { CHANNEL })
1403 def getMdDate(File mdFile) {
1404 return mdFileComponents(mdFile, true)
1407 def getMdSections(String content) {
1409 def sectionContent = ""
1410 def sectionName = null
1411 content.eachLine { line ->
1413 if (m = line =~ /^##([^#].*)$/) {
1414 if (sectionName != null) {
1415 sections[sectionName] = sectionContent
1419 sectionName = m[0][1].trim()
1420 sectionName = sectionName.toLowerCase()
1421 sectionName = sectionName.replaceAll(/ +/, "_")
1422 sectionName = sectionName.replaceAll(/[^a-z0-9_\-]/, "")
1423 } else if (sectionName != null) {
1424 sectionContent += line+"\n"
1427 if (sectionContent != null) {
1428 sections[sectionName] = sectionContent
1434 task copyHelp(type: Copy) {
1435 def inputDir = helpSourceDir
1436 def outputDir = "${helpBuildDir}/${help_dir}"
1440 include('**/*.html')
1444 filter(ReplaceTokens,
1448 'Version-Rel': JALVIEW_VERSION,
1449 'Year-Rel': getDate("yyyy")
1456 exclude('**/*.html')
1463 inputs.dir(inputDir)
1464 outputs.files(helpFile)
1465 outputs.dir(outputDir)
1469 task releasesTemplates {
1471 description "Recreate whatsNew.html and releases.html from markdown files and templates in help"
1475 def releasesTemplateFile = file("${jalviewDir}/${releases_template}")
1476 def whatsnewTemplateFile = file("${jalviewDir}/${whatsnew_template}")
1477 def releasesHtmlFile = file("${helpBuildDir}/${help_dir}/${releases_html}")
1478 def whatsnewHtmlFile = file("${helpBuildDir}/${help_dir}/${whatsnew_html}")
1479 def releasesMdDir = "${jalviewDir}/${releases_dir}"
1480 def whatsnewMdDir = "${jalviewDir}/${whatsnew_dir}"
1483 def releaseMdFile = file("${releasesMdDir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1484 def whatsnewMdFile = file("${whatsnewMdDir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1486 if (CHANNEL == "RELEASE") {
1487 if (!releaseMdFile.exists()) {
1488 throw new GradleException("File ${releaseMdFile} must be created for RELEASE")
1490 if (!whatsnewMdFile.exists()) {
1491 throw new GradleException("File ${whatsnewMdFile} must be created for RELEASE")
1495 def releaseFiles = fileTree(dir: releasesMdDir, include: "release-*.md")
1496 def releaseFilesDates = releaseFiles.collectEntries {
1497 [(it): getMdDate(it)]
1499 releaseFiles = releaseFiles.sort { a,b -> releaseFilesDates[a].compareTo(releaseFilesDates[b]) }
1501 def releasesTemplate = releasesTemplateFile.text
1502 def m = releasesTemplate =~ /(?s)__VERSION_LOOP_START__(.*)__VERSION_LOOP_END__/
1503 def versionTemplate = m[0][1]
1505 MutableDataSet options = new MutableDataSet()
1507 def extensions = new ArrayList<>()
1508 options.set(Parser.EXTENSIONS, extensions)
1509 options.set(Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE, true)
1511 Parser parser = Parser.builder(options).build()
1512 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1514 def actualVersions = releaseFiles.collect { rf ->
1515 def (rfMap, rfContent) = mdFileComponents(rf)
1516 return rfMap.version
1518 def versionsHtml = ""
1519 def linkedVersions = []
1520 releaseFiles.reverse().each { rFile ->
1521 def (rMap, rContent) = mdFileComponents(rFile)
1523 def versionLink = ""
1524 def partialVersion = ""
1525 def firstPart = true
1526 rMap.version.split("\\.").each { part ->
1527 def displayPart = ( firstPart ? "" : "." ) + part
1528 partialVersion += displayPart
1530 linkedVersions.contains(partialVersion)
1531 || ( actualVersions.contains(partialVersion) && partialVersion != rMap.version )
1533 versionLink += displayPart
1535 versionLink += "<a id=\"Jalview.${partialVersion}\">${displayPart}</a>"
1536 linkedVersions += partialVersion
1540 def displayDate = releaseFilesDates[rFile].format("dd/MM/yyyy")
1543 def rContentProcessed = ""
1544 rContent.eachLine { line ->
1545 if (lm = line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
1546 line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}"
1547 } else if (lm = line =~ /^###([^#]+.*)$/) {
1548 line = "_${lm[0][1].trim()}_"
1550 rContentProcessed += line + "\n"
1553 def rContentSections = getMdSections(rContentProcessed)
1554 def rVersion = versionTemplate
1555 if (rVersion != "") {
1556 def rNewFeatures = rContentSections["new_features"]
1557 def rIssuesResolved = rContentSections["issues_resolved"]
1558 Node newFeaturesNode = parser.parse(rNewFeatures)
1559 String newFeaturesHtml = renderer.render(newFeaturesNode)
1560 Node issuesResolvedNode = parser.parse(rIssuesResolved)
1561 String issuesResolvedHtml = renderer.render(issuesResolvedNode)
1562 rVersion = hugoTemplateSubstitutions(rVersion,
1564 VERSION: rMap.version,
1565 VERSION_LINK: versionLink,
1566 DISPLAY_DATE: displayDate,
1567 NEW_FEATURES: newFeaturesHtml,
1568 ISSUES_RESOLVED: issuesResolvedHtml
1571 versionsHtml += rVersion
1575 releasesTemplate = releasesTemplate.replaceAll("(?s)__VERSION_LOOP_START__.*__VERSION_LOOP_END__", versionsHtml)
1576 releasesTemplate = hugoTemplateSubstitutions(releasesTemplate)
1577 releasesHtmlFile.text = releasesTemplate
1579 if (whatsnewMdFile.exists()) {
1580 def wnDisplayDate = releaseFilesDates[releaseMdFile] != null ? releaseFilesDates[releaseMdFile].format("dd MMMM yyyy") : ""
1581 def whatsnewMd = hugoTemplateSubstitutions(whatsnewMdFile.text)
1582 Node whatsnewNode = parser.parse(whatsnewMd)
1583 String whatsnewHtml = renderer.render(whatsnewNode)
1584 whatsnewHtml = whatsnewTemplateFile.text.replaceAll("__WHATS_NEW__", whatsnewHtml)
1585 whatsnewHtmlFile.text = hugoTemplateSubstitutions(whatsnewHtml,
1587 VERSION: JALVIEW_VERSION,
1588 DISPLAY_DATE: wnDisplayDate
1591 } else if (gradle.taskGraph.hasTask(":linkCheck")) {
1592 whatsnewHtmlFile.text = "Development build " + getDate("yyyy-MM-dd HH:mm:ss")
1597 inputs.file(releasesTemplateFile)
1598 inputs.file(whatsnewTemplateFile)
1599 inputs.dir(releasesMdDir)
1600 inputs.dir(whatsnewMdDir)
1601 outputs.file(releasesHtmlFile)
1602 outputs.file(whatsnewHtmlFile)
1606 task copyResources(type: Copy) {
1608 description = "Copy (and make text substitutions in) the resources dir to the build area"
1610 def inputDir = resourceDir
1611 def outputDir = resourcesBuildDir
1615 include('**/*.html')
1617 filter(ReplaceTokens,
1621 'Version-Rel': JALVIEW_VERSION,
1622 'Year-Rel': getDate("yyyy")
1629 exclude('**/*.html')
1634 inputs.dir(inputDir)
1635 outputs.dir(outputDir)
1638 task copyChannelResources(type: Copy) {
1639 dependsOn copyResources
1641 description = "Copy the channel resources dir to the build resources area"
1643 def inputDir = "${channelDir}/${resource_dir}"
1644 def outputDir = resourcesBuildDir
1646 include(channel_props)
1647 filter(ReplaceTokens,
1651 'SUFFIX': channelSuffix
1656 exclude(channel_props)
1660 inputs.dir(inputDir)
1661 outputs.dir(outputDir)
1664 task createBuildProperties(type: WriteProperties) {
1665 dependsOn copyResources
1667 description = "Create the ${buildProperties} file"
1669 inputs.dir(sourceDir)
1670 inputs.dir(resourcesBuildDir)
1671 outputFile (buildProperties)
1672 // taking time specific comment out to allow better incremental builds
1673 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1674 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1675 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1676 property "VERSION", JALVIEW_VERSION
1677 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1678 property "JAVA_COMPILE_VERSION", JAVA_INTEGER_VERSION
1679 if (getdownSetAppBaseProperty) {
1680 property "GETDOWNAPPBASE", getdownAppBase
1681 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1683 outputs.file(outputFile)
1687 task buildIndices(type: JavaExec) {
1689 classpath = sourceSets.main.compileClasspath
1690 main = "com.sun.java.help.search.Indexer"
1691 workingDir = "${helpBuildDir}/${help_dir}"
1694 inputs.dir("${workingDir}/${argDir}")
1696 outputs.dir("${classesDir}/doc")
1697 outputs.dir("${classesDir}/help")
1698 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1699 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1700 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1701 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1702 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1703 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1706 task buildResources {
1707 dependsOn copyResources
1708 dependsOn copyChannelResources
1709 dependsOn createBuildProperties
1713 dependsOn buildResources
1716 dependsOn releasesTemplates
1717 dependsOn convertMdFiles
1718 dependsOn buildIndices
1722 compileJava.dependsOn prepare
1723 run.dependsOn compileJava
1724 //run.dependsOn prepare
1727 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1732 dependsOn cloverClasses
1734 dependsOn compileJava //?
1738 includeGroups testng_groups
1739 excludeGroups testng_excluded_groups
1741 useDefaultListeners=true
1744 maxHeapSize = "1024m"
1746 workingDir = jalviewDir
1747 def testLaf = project.findProperty("test_laf")
1748 if (testLaf != null) {
1749 println("Setting Test LaF to '${testLaf}'")
1750 systemProperty "laf", testLaf
1752 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1753 if (testHiDPIScale != null) {
1754 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1755 systemProperty "sun.java2d.uiScale", testHiDPIScale
1757 sourceCompatibility = compile_source_compatibility
1758 targetCompatibility = compile_target_compatibility
1759 jvmArgs += additional_compiler_args
1763 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1769 task compileLinkCheck(type: JavaCompile) {
1771 classpath = files("${jalviewDir}/${utils_dir}")
1772 destinationDir = file("${jalviewDir}/${utils_dir}")
1773 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1775 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1776 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1777 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1778 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1782 task linkCheck(type: JavaExec) {
1784 dependsOn compileLinkCheck
1786 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1787 classpath = files("${jalviewDir}/${utils_dir}")
1788 main = "HelpLinksChecker"
1789 workingDir = "${helpBuildDir}"
1790 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1792 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1793 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1796 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1800 inputs.dir(helpBuildDir)
1801 outputs.file(helpLinksCheckerOutFile)
1805 // import the pubhtmlhelp target
1806 ant.properties.basedir = "${jalviewDir}"
1807 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1808 ant.importBuild "${utils_dir}/publishHelp.xml"
1811 task cleanPackageDir(type: Delete) {
1813 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1823 attributes "Main-Class": main_class,
1824 "Permissions": "all-permissions",
1825 "Application-Name": applicationName,
1826 "Codebase": application_codebase,
1827 "Implementation-Version": JALVIEW_VERSION
1830 def outputDir = "${jalviewDir}/${package_dir}"
1831 destinationDirectory = file(outputDir)
1832 archiveFileName = rootProject.name+".jar"
1833 duplicatesStrategy "EXCLUDE"
1840 exclude "**/*.jar.*"
1842 inputs.dir(sourceSets.main.java.outputDir)
1843 sourceSets.main.resources.srcDirs.each{ dir ->
1846 outputs.file("${outputDir}/${archiveFileName}")
1850 task copyJars(type: Copy) {
1851 from fileTree(dir: classesDir, include: "**/*.jar").files
1852 into "${jalviewDir}/${package_dir}"
1856 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1857 task syncJars(type: Sync) {
1859 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1860 into "${jalviewDir}/${package_dir}"
1862 include jar.archiveFileName.getOrNull()
1869 description = "Put all required libraries in dist"
1870 // order of "cleanPackageDir", "copyJars", "jar" important!
1871 jar.mustRunAfter cleanPackageDir
1872 syncJars.mustRunAfter cleanPackageDir
1873 dependsOn cleanPackageDir
1876 outputs.dir("${jalviewDir}/${package_dir}")
1881 dependsOn cleanPackageDir
1888 group = "distribution"
1889 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1893 from ("${jalviewDir}/${libDistDir}") {
1897 attributes "Implementation-Version": JALVIEW_VERSION,
1898 "Application-Name": applicationName
1901 duplicatesStrategy "INCLUDE"
1903 mainClassName = shadow_jar_main_class
1905 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1910 task getdownWebsite() {
1911 group = "distribution"
1912 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1917 def getdownWebsiteResourceFilenames = []
1918 def getdownResourceDir = getdownResourceDir
1919 def getdownResourceFilenames = []
1922 // clean the getdown website and files dir before creating getdown folders
1923 delete getdownAppBaseDir
1924 delete getdownFilesDir
1927 from buildProperties
1928 rename(file(buildProperties).getName(), getdown_build_properties)
1931 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1934 from channelPropsFile
1935 filter(ReplaceTokens,
1939 'SUFFIX': channelSuffix
1942 into getdownAppBaseDir
1944 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1946 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1947 def props = project.properties.sort { it.key }
1948 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1949 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1951 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1952 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1954 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1955 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1957 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1958 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1959 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1960 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1961 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1962 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1963 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1966 props.put("getdown_txt_title", jalview_name)
1967 props.put("getdown_txt_ui.name", applicationName)
1969 // start with appbase
1970 getdownTextLines += "appbase = ${getdownAppBase}"
1971 props.each{ prop, val ->
1972 if (prop.startsWith("getdown_txt_") && val != null) {
1973 if (prop.startsWith("getdown_txt_multi_")) {
1974 def key = prop.substring(18)
1975 val.split(",").each{ v ->
1976 def line = "${key} = ${v}"
1977 getdownTextLines += line
1980 // file values rationalised
1981 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1983 if (val.indexOf('/') == 0) {
1986 } else if (val.indexOf('/') > 0) {
1987 // relative path (relative to jalviewDir)
1988 r = file( "${jalviewDir}/${val}" )
1991 val = "${getdown_resource_dir}/" + r.getName()
1992 getdownWebsiteResourceFilenames += val
1993 getdownResourceFilenames += r.getPath()
1996 if (! prop.startsWith("getdown_txt_resource")) {
1997 def line = prop.substring(12) + " = ${val}"
1998 getdownTextLines += line
2004 getdownWebsiteResourceFilenames.each{ filename ->
2005 getdownTextLines += "resource = ${filename}"
2007 getdownResourceFilenames.each{ filename ->
2010 into getdownResourceDir
2014 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
2015 getdownWrapperScripts.each{ script ->
2016 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
2020 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
2022 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
2027 fileTree(file(package_dir)).each{ f ->
2028 if (f.isDirectory()) {
2029 def files = fileTree(dir: f, include: ["*"]).getFiles()
2031 } else if (f.exists()) {
2035 def jalviewJar = jar.archiveFileName.getOrNull()
2036 // put jalview.jar first for CLASSPATH and .properties files reasons
2037 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
2038 def name = f.getName()
2039 def line = "code = ${getdownAppDistDir}/${name}"
2040 getdownTextLines += line
2047 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
2049 if (JAVA_VERSION.equals("11")) {
2050 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
2051 j11libFiles.sort().each{f ->
2052 def name = f.getName()
2053 def line = "code = ${getdown_j11lib_dir}/${name}"
2054 getdownTextLines += line
2057 into getdownJ11libDir
2063 // 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.
2064 //getdownTextLines += "class = " + file(getdownLauncher).getName()
2065 getdownTextLines += "resource = ${getdown_launcher_new}"
2066 getdownTextLines += "class = ${main_class}"
2067 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
2068 if (getdownSetAppBaseProperty) {
2069 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
2070 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
2073 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
2074 getdownTxt.write(getdownTextLines.join("\n"))
2076 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
2077 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
2078 launchJvl.write("appbase=${getdownAppBase}")
2080 // files going into the getdown website dir: getdown-launcher.jar
2082 from getdownLauncher
2083 rename(file(getdownLauncher).getName(), getdown_launcher_new)
2084 into getdownAppBaseDir
2087 // files going into the getdown website dir: getdown-launcher(-local).jar
2089 from getdownLauncher
2090 if (file(getdownLauncher).getName() != getdown_launcher) {
2091 rename(file(getdownLauncher).getName(), getdown_launcher)
2093 into getdownAppBaseDir
2096 // files going into the getdown website dir: ./install dir and files
2097 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
2100 from getdownLauncher
2101 from "${getdownAppDir}/${getdown_build_properties}"
2102 if (file(getdownLauncher).getName() != getdown_launcher) {
2103 rename(file(getdownLauncher).getName(), getdown_launcher)
2105 into getdownInstallDir
2108 // and make a copy in the getdown files dir (these are not downloaded by getdown)
2110 from getdownInstallDir
2111 into getdownFilesInstallDir
2115 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2119 from getdownLauncher
2120 from "${getdownAppBaseDir}/${getdown_build_properties}"
2121 from "${getdownAppBaseDir}/${channel_props}"
2122 if (file(getdownLauncher).getName() != getdown_launcher) {
2123 rename(file(getdownLauncher).getName(), getdown_launcher)
2125 into getdownFilesDir
2128 // and ./resource (not all downloaded by getdown)
2130 from getdownResourceDir
2131 into "${getdownFilesDir}/${getdown_resource_dir}"
2136 inputs.dir("${jalviewDir}/${package_dir}")
2138 outputs.dir(getdownAppBaseDir)
2139 outputs.dir(getdownFilesDir)
2143 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
2144 task getdownDigestDir(type: JavaExec) {
2146 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
2148 def digestDirPropertyName = "DIGESTDIR"
2150 classpath = files(getdownLauncher)
2151 def digestDir = findProperty(digestDirPropertyName)
2152 if (digestDir == null) {
2153 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
2157 main = "com.threerings.getdown.tools.Digester"
2161 task getdownDigest(type: JavaExec) {
2162 group = "distribution"
2163 description = "Digest the getdown website folder"
2164 dependsOn getdownWebsite
2166 classpath = files(getdownLauncher)
2168 main = "com.threerings.getdown.tools.Digester"
2169 args getdownAppBaseDir
2170 inputs.dir(getdownAppBaseDir)
2171 outputs.file("${getdownAppBaseDir}/digest2.txt")
2176 group = "distribution"
2177 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
2178 dependsOn getdownDigest
2180 if (reportRsyncCommand) {
2181 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
2182 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
2183 println "LIKELY RSYNC COMMAND:"
2184 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
2185 if (RUNRSYNC == "true") {
2187 commandLine "mkdir", "-p", toDir
2190 commandLine "rsync", "-avh", "--delete", fromDir, toDir
2198 task getdownArchiveBuild() {
2199 group = "distribution"
2200 description = "Put files in the archive dir to go on the website"
2202 dependsOn getdownWebsite
2204 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
2205 def vDir = "${getdownArchiveDir}/${v}"
2206 getdownFullArchiveDir = "${vDir}/getdown"
2207 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
2209 def vAltDir = "alt_${v}"
2210 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
2213 // cleanup old "old" dir
2214 delete getdownArchiveDir
2216 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
2217 getdownArchiveTxt.getParentFile().mkdirs()
2218 def getdownArchiveTextLines = []
2219 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
2223 from "${getdownAppBaseDir}/${getdownAppDistDir}"
2224 into "${getdownFullArchiveDir}/${vAltDir}"
2227 getdownTextLines.each { line ->
2228 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
2229 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
2230 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
2231 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
2232 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
2233 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
2234 // remove the existing resource = resource/ or bin/ lines
2235 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
2236 getdownArchiveTextLines += line
2240 // the resource dir -- add these files as resource lines in getdown.txt
2242 from "${archiveImagesDir}"
2243 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
2245 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
2249 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
2251 def vLaunchJvl = file(getdownVersionLaunchJvl)
2252 vLaunchJvl.getParentFile().mkdirs()
2253 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
2254 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
2255 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
2256 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
2257 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
2258 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
2260 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2262 from getdownLauncher
2263 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
2264 from "${getdownAppBaseDir}/${getdown_launcher_new}"
2265 from "${getdownAppBaseDir}/${channel_props}"
2266 if (file(getdownLauncher).getName() != getdown_launcher) {
2267 rename(file(getdownLauncher).getName(), getdown_launcher)
2269 into getdownFullArchiveDir
2275 task getdownArchiveDigest(type: JavaExec) {
2276 group = "distribution"
2277 description = "Digest the getdown archive folder"
2279 dependsOn getdownArchiveBuild
2282 classpath = files(getdownLauncher)
2283 args getdownFullArchiveDir
2285 main = "com.threerings.getdown.tools.Digester"
2286 inputs.dir(getdownFullArchiveDir)
2287 outputs.file("${getdownFullArchiveDir}/digest2.txt")
2290 task getdownArchive() {
2291 group = "distribution"
2292 description = "Build the website archive dir with getdown digest"
2294 dependsOn getdownArchiveBuild
2295 dependsOn getdownArchiveDigest
2298 tasks.withType(JavaCompile) {
2299 options.encoding = 'UTF-8'
2305 delete getdownAppBaseDir
2306 delete getdownFilesDir
2307 delete getdownArchiveDir
2313 if (file(install4jHomeDir).exists()) {
2315 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
2316 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
2317 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
2318 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
2320 installDir(file(install4jHomeDir))
2322 mediaTypes = Arrays.asList(install4j_media_types.split(","))
2326 task copyInstall4jTemplate {
2327 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
2328 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
2329 inputs.file(install4jTemplateFile)
2330 inputs.file(install4jFileAssociationsFile)
2331 inputs.property("CHANNEL", { CHANNEL })
2332 outputs.file(install4jConfFile)
2335 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
2337 // turn off code signing if no OSX_KEYPASS
2338 if (OSX_KEYPASS == "") {
2339 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
2340 codeSigning.'@macEnabled' = "false"
2342 install4jConfigXml.'**'.windows.each { windows ->
2343 windows.'@runPostProcessor' = "false"
2347 // disable install screen for OSX dmg (for 2.11.2.0)
2348 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
2349 macosArchive.attributes().remove('executeSetupApp')
2350 macosArchive.attributes().remove('setupAppId')
2353 // turn off checksum creation for LOCAL channel
2354 def e = install4jConfigXml.application[0]
2355 e.'@createChecksums' = string(install4jCheckSums)
2357 // put file association actions where placeholder action is
2358 def install4jFileAssociationsText = install4jFileAssociationsFile.text
2359 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
2360 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
2361 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
2362 def parent = a.parent()
2364 fileAssociationActions.each { faa ->
2367 // don't need to continue in .any loop once replacements have been made
2372 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
2373 // NB we're deleting the /other/ one!
2374 // Also remove the examples subdir from non-release versions
2375 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
2376 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
2377 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
2378 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
2380 // remove the examples subdir from Full File Set
2381 def files = install4jConfigXml.files[0]
2382 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
2383 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
2384 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
2385 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
2386 dirEntry.parent().remove(dirEntry)
2388 install4jConfigXml.'**'.action.any { a ->
2389 if (a.'@customizedId' == customizedIdToDelete) {
2390 def parent = a.parent()
2396 // write install4j file
2397 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2404 delete install4jConfFile
2408 task cleanInstallersDataFiles {
2409 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2410 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2411 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2413 delete installersOutputTxt
2414 delete installersSha256
2415 delete hugoDataJsonFile
2419 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2420 group = "distribution"
2421 description = "Create the install4j installers"
2423 dependsOn copyInstall4jTemplate
2424 dependsOn cleanInstallersDataFiles
2426 projectFile = install4jConfFile
2428 // create an md5 for the input files to use as version for install4j conf file
2429 def digest = MessageDigest.getInstance("MD5")
2431 (file("${install4jDir}/${install4j_template}").text +
2432 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2433 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2434 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2435 if (filesMd5.length() >= 8) {
2436 filesMd5 = filesMd5.substring(0,8)
2438 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2441 'JALVIEW_NAME': jalview_name,
2442 'JALVIEW_APPLICATION_NAME': applicationName,
2443 'JALVIEW_DIR': "../..",
2444 'OSX_KEYSTORE': OSX_KEYSTORE,
2445 'OSX_APPLEID': OSX_APPLEID,
2446 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2447 'JSIGN_SH': JSIGN_SH,
2448 'JRE_DIR': getdown_app_dir_java,
2449 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2450 'JALVIEW_VERSION': JALVIEW_VERSION,
2451 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2452 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2453 'JAVA_VERSION': JAVA_VERSION,
2454 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2455 'VERSION': JALVIEW_VERSION,
2456 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2457 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2458 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2459 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2460 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2461 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2462 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2463 'BUNDLE_ID': install4jBundleId,
2464 'INTERNAL_ID': install4jInternalId,
2465 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2466 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2467 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2468 'WRAPPER_LINK': getdownWrapperLink,
2469 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2470 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2471 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2472 'INSTALLER_NAME': install4jInstallerName,
2473 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2474 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2475 'GETDOWN_FILES_DIR': getdown_files_dir,
2476 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2477 'GETDOWN_DIST_DIR': getdownAppDistDir,
2478 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2479 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2480 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2481 'BUILD_DIR': install4jBuildDir,
2482 'APPLICATION_CATEGORIES': install4j_application_categories,
2483 'APPLICATION_FOLDER': install4jApplicationFolder,
2484 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2485 'EXECUTABLE_NAME': install4jExecutableName,
2486 'EXTRA_SCHEME': install4jExtraScheme,
2487 'MAC_ICONS_FILE': install4jMacIconsFile,
2488 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2489 'PNG_ICON_FILE': install4jPngIconFile,
2490 'BACKGROUND': install4jBackground,
2494 //println("INSTALL4J VARIABLES:")
2495 //variables.each{k,v->println("${k}=${v}")}
2497 destination = "${jalviewDir}/${install4jBuildDir}"
2498 buildSelected = true
2500 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2502 disableSigning = true
2503 disableNotarization = true
2507 macKeystorePassword = OSX_KEYPASS
2510 if (OSX_ALTOOLPASS) {
2511 appleIdPassword = OSX_ALTOOLPASS
2512 disableNotarization = false
2514 disableNotarization = true
2518 println("Using projectFile "+projectFile)
2519 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2523 inputs.dir(getdownAppBaseDir)
2524 inputs.file(install4jConfFile)
2525 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2526 inputs.dir(macosJavaVMDir)
2527 inputs.dir(windowsJavaVMDir)
2528 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2531 def getDataHash(File myFile) {
2532 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2533 return myFile.exists()
2535 "file" : myFile.getName(),
2536 "filesize" : myFile.length(),
2537 "sha256" : hash.toString()
2542 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2544 "channel" : getdownChannelName,
2545 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2546 "git-commit" : "${gitHash} [${gitBranch}]",
2547 "version" : JALVIEW_VERSION
2549 // install4j installer files
2550 if (installersOutputTxt.exists()) {
2552 installersOutputTxt.readLines().each { def line ->
2553 if (line.startsWith("#")) {
2556 line.replaceAll("\n","")
2557 def vals = line.split("\t")
2558 def filename = vals[3]
2559 def filesize = file(filename).length()
2560 filename = filename.replaceAll(/^.*\//, "")
2561 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2562 idHash."${filename}" = vals[0]
2564 if (install4jCheckSums && installersSha256.exists()) {
2565 installersSha256.readLines().each { def line ->
2566 if (line.startsWith("#")) {
2569 line.replaceAll("\n","")
2570 def vals = line.split(/\s+\*?/)
2571 def filename = vals[1]
2572 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2578 "JAR": shadowJar.archiveFile, // executable JAR
2579 "JVL": getdownVersionLaunchJvl, // version JVL
2580 "SOURCE": sourceDist.archiveFile // source TGZ
2581 ].each { key, value ->
2582 def file = file(value)
2583 if (file.exists()) {
2584 def fileHash = getDataHash(file)
2585 if (fileHash != null) {
2586 hash."${key}" = fileHash;
2590 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2593 task staticMakeInstallersJsonFile {
2595 def output = findProperty("i4j_output")
2596 def sha256 = findProperty("i4j_sha256")
2597 def json = findProperty("i4j_json")
2598 if (output == null || sha256 == null || json == null) {
2599 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2601 writeDataJsonFile(file(output), file(sha256), file(json))
2606 dependsOn installerFiles
2612 eclipse().configFile(eclipse_codestyle_file)
2616 task createSourceReleaseProperties(type: WriteProperties) {
2617 group = "distribution"
2618 description = "Create the source RELEASE properties file"
2620 def sourceTarBuildDir = "${buildDir}/sourceTar"
2621 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2622 outputFile (sourceReleasePropertiesFile)
2625 releaseProps.each{ key, val -> property key, val }
2626 property "git.branch", gitBranch
2627 property "git.hash", gitHash
2630 outputs.file(outputFile)
2633 task sourceDist(type: Tar) {
2634 group "distribution"
2635 description "Create a source .tar.gz file for distribution"
2637 dependsOn createBuildProperties
2638 dependsOn convertMdFiles
2639 dependsOn eclipseAllPreferences
2640 dependsOn createSourceReleaseProperties
2643 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2644 archiveFileName = outputFileName
2646 compression Compression.GZIP
2661 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2663 "utils/InstallAnywhere",
2678 "gradle.properties",
2690 ".settings/org.eclipse.buildship.core.prefs",
2691 ".settings/org.eclipse.jdt.core.prefs"
2695 exclude (EXCLUDE_FILES)
2696 include (PROCESS_FILES)
2697 filter(ReplaceTokens,
2701 'Version-Rel': JALVIEW_VERSION,
2702 'Year-Rel': getDate("yyyy")
2707 exclude (EXCLUDE_FILES)
2708 exclude (PROCESS_FILES)
2709 exclude ("appletlib")
2710 exclude ("**/*locales")
2711 exclude ("*locales/**")
2712 exclude ("utils/InstallAnywhere")
2714 exclude (getdown_files_dir)
2715 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2716 //exclude (getdown_website_dir)
2717 //exclude (getdown_archive_dir)
2719 // exluding these as not using jars as modules yet
2720 exclude ("${j11modDir}/**/*.jar")
2723 include(INCLUDE_FILES)
2725 // from (jalviewDir) {
2726 // // explicit includes for stuff that seemed to not get included
2727 // include(fileTree("test/**/*."))
2728 // exclude(EXCLUDE_FILES)
2729 // exclude(PROCESS_FILES)
2732 from(file(buildProperties).getParent()) {
2733 include(file(buildProperties).getName())
2734 rename(file(buildProperties).getName(), "build_properties")
2736 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2740 def sourceTarBuildDir = "${buildDir}/sourceTar"
2741 from(sourceTarBuildDir) {
2742 // this includes the appended RELEASE properties file
2746 task dataInstallersJson {
2748 description "Create the installers-VERSION.json data file for installer files created"
2750 mustRunAfter installers
2751 mustRunAfter shadowJar
2752 mustRunAfter sourceDist
2753 mustRunAfter getdownArchive
2755 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2756 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2758 if (installersOutputTxt.exists()) {
2759 inputs.file(installersOutputTxt)
2761 if (install4jCheckSums && installersSha256.exists()) {
2762 inputs.file(installersSha256)
2765 shadowJar.archiveFile, // executable JAR
2766 getdownVersionLaunchJvl, // version JVL
2767 sourceDist.archiveFile // source TGZ
2768 ].each { fileName ->
2769 if (file(fileName).exists()) {
2770 inputs.file(fileName)
2774 outputs.file(hugoDataJsonFile)
2777 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2783 description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'."
2786 dependsOn pubhtmlhelp
2788 inputs.dir("${helpBuildDir}/${help_dir}")
2789 outputs.dir("${buildDir}/distributions/${help_dir}")
2793 task j2sSetHeadlessBuild {
2800 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2802 description "Enable the alternative J2S Config file for headless build"
2804 outputFile = jalviewjsJ2sSettingsFileName
2805 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2806 def j2sProps = new Properties()
2807 if (j2sPropsFile.exists()) {
2809 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2810 j2sProps.load(j2sPropsFileFIS)
2811 j2sPropsFileFIS.close()
2813 j2sProps.each { prop, val ->
2816 } catch (Exception e) {
2817 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2821 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2822 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2827 task jalviewjsSetEclipseWorkspace {
2828 def propKey = "jalviewjs_eclipse_workspace"
2830 if (project.hasProperty(propKey)) {
2831 propVal = project.getProperty(propKey)
2832 if (propVal.startsWith("~/")) {
2833 propVal = System.getProperty("user.home") + propVal.substring(1)
2836 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2837 def propsFile = file(propsFileName)
2838 def eclipseWsDir = propVal
2839 def props = new Properties()
2841 def writeProps = true
2842 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2843 def ins = new FileInputStream(propsFileName)
2846 if (props.getProperty(propKey, null) != null) {
2847 eclipseWsDir = props.getProperty(propKey)
2852 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2853 def tempDir = File.createTempDir()
2854 eclipseWsDir = tempDir.getAbsolutePath()
2857 eclipseWorkspace = file(eclipseWsDir)
2860 // do not run a headless transpile when we claim to be in Eclipse
2862 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2863 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2865 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2869 props.setProperty(propKey, eclipseWsDir)
2870 propsFile.parentFile.mkdirs()
2871 def bytes = new ByteArrayOutputStream()
2872 props.store(bytes, null)
2873 def propertiesString = bytes.toString()
2874 propsFile.text = propertiesString
2880 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2883 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2884 outputs.file(propsFileName)
2885 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2889 task jalviewjsEclipsePaths {
2892 def eclipseRoot = jalviewjs_eclipse_root
2893 if (eclipseRoot.startsWith("~/")) {
2894 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2896 if (OperatingSystem.current().isMacOsX()) {
2897 eclipseRoot += "/Eclipse.app"
2898 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2899 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2900 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2901 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2902 eclipseRoot += "/eclipse"
2904 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2905 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2906 } else { // linux or unix
2907 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2908 eclipseRoot += "/eclipse"
2909 println("eclipseDir exists")
2911 eclipseBinary = "${eclipseRoot}/eclipse"
2912 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2915 eclipseVersion = "4.13" // default
2916 def assumedVersion = true
2917 if (file(eclipseProduct).exists()) {
2918 def fis = new FileInputStream(eclipseProduct)
2919 def props = new Properties()
2921 eclipseVersion = props.getProperty("version")
2923 assumedVersion = false
2926 def propKey = "eclipse_debug"
2927 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2930 // do not run a headless transpile when we claim to be in Eclipse
2932 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2933 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2935 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2938 if (!assumedVersion) {
2939 println("ECLIPSE VERSION=${eclipseVersion}")
2945 task printProperties {
2947 description "Output to console all System.properties"
2949 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2955 dependsOn eclipseProject
2956 dependsOn eclipseClasspath
2957 dependsOn eclipseJdt
2961 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2962 task jalviewjsEclipseCopyDropins(type: Copy) {
2963 dependsOn jalviewjsEclipsePaths
2965 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2966 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2967 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2974 // this eclipse -clean doesn't actually work
2975 task jalviewjsCleanEclipse(type: Exec) {
2976 dependsOn eclipseSetup
2977 dependsOn jalviewjsEclipsePaths
2978 dependsOn jalviewjsEclipseCopyDropins
2980 executable(eclipseBinary)
2981 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2987 def inputString = """exit
2990 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2991 standardInput = inputByteStream
2994 /* not really working yet
2995 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2999 task jalviewjsTransferUnzipSwingJs {
3000 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
3004 from zipTree(file_zip)
3005 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3009 inputs.file file_zip
3010 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3014 task jalviewjsTransferUnzipLib {
3015 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
3018 zipFiles.each { file_zip ->
3020 from zipTree(file_zip)
3021 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3026 inputs.files zipFiles
3027 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3031 task jalviewjsTransferUnzipAllLibs {
3032 dependsOn jalviewjsTransferUnzipSwingJs
3033 dependsOn jalviewjsTransferUnzipLib
3037 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
3039 description "Create the alternative j2s file from the j2s.* properties"
3041 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
3042 def siteDirProperty = "j2s.site.directory"
3043 def setSiteDir = false
3044 jalviewjsJ2sProps.each { prop, val ->
3046 if (prop == siteDirProperty) {
3047 if (!(val.startsWith('/') || val.startsWith("file://") )) {
3048 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3054 if (!setSiteDir) { // default site location, don't override specifically set property
3055 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3058 outputFile = jalviewjsJ2sAltSettingsFileName
3061 inputs.properties(jalviewjsJ2sProps)
3062 outputs.file(jalviewjsJ2sAltSettingsFileName)
3067 task jalviewjsEclipseSetup {
3068 dependsOn jalviewjsEclipseCopyDropins
3069 dependsOn jalviewjsSetEclipseWorkspace
3070 dependsOn jalviewjsCreateJ2sSettings
3074 task jalviewjsSyncAllLibs (type: Sync) {
3075 dependsOn jalviewjsTransferUnzipAllLibs
3076 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3077 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3078 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3082 def outputFiles = []
3083 rename { filename ->
3084 outputFiles += "${outputDir}/${filename}"
3091 // should this be exclude really ?
3092 duplicatesStrategy "INCLUDE"
3094 outputs.files outputFiles
3095 inputs.files inputFiles
3099 task jalviewjsSyncResources (type: Sync) {
3100 dependsOn buildResources
3102 def inputFiles = fileTree(dir: resourcesBuildDir)
3103 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3107 def outputFiles = []
3108 rename { filename ->
3109 outputFiles += "${outputDir}/${filename}"
3115 outputs.files outputFiles
3116 inputs.files inputFiles
3120 task jalviewjsSyncSiteResources (type: Sync) {
3121 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3122 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3126 def outputFiles = []
3127 rename { filename ->
3128 outputFiles += "${outputDir}/${filename}"
3134 outputs.files outputFiles
3135 inputs.files inputFiles
3139 task jalviewjsSyncBuildProperties (type: Sync) {
3140 dependsOn createBuildProperties
3141 def inputFiles = [file(buildProperties)]
3142 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3146 def outputFiles = []
3147 rename { filename ->
3148 outputFiles += "${outputDir}/${filename}"
3154 outputs.files outputFiles
3155 inputs.files inputFiles
3159 task jalviewjsProjectImport(type: Exec) {
3160 dependsOn eclipseSetup
3161 dependsOn jalviewjsEclipsePaths
3162 dependsOn jalviewjsEclipseSetup
3165 // do not run a headless import when we claim to be in Eclipse
3167 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3168 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3170 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3174 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3175 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3176 executable(eclipseBinary)
3177 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3181 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3183 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3184 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3187 inputs.file("${jalviewDir}/.project")
3188 outputs.upToDateWhen {
3189 file(projdir).exists()
3194 task jalviewjsTranspile(type: Exec) {
3195 dependsOn jalviewjsEclipseSetup
3196 dependsOn jalviewjsProjectImport
3197 dependsOn jalviewjsEclipsePaths
3199 dependsOn jalviewjsEnableAltFileProperty
3203 // do not run a headless transpile when we claim to be in Eclipse
3205 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3206 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3208 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3212 executable(eclipseBinary)
3213 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3217 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3219 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3220 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3226 stdout = new ByteArrayOutputStream()
3227 stderr = new ByteArrayOutputStream()
3229 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3230 def logOutFile = file(logOutFileName)
3231 logOutFile.createNewFile()
3232 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3233 BINARY: ${eclipseBinary}
3234 VERSION: ${eclipseVersion}
3235 WORKSPACE: ${eclipseWorkspace}
3236 DEBUG: ${eclipseDebug}
3239 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3240 // combine stdout and stderr
3241 def logErrFOS = logOutFOS
3243 if (jalviewjs_j2s_to_console.equals("true")) {
3244 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3245 new org.apache.tools.ant.util.TeeOutputStream(
3249 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3250 new org.apache.tools.ant.util.TeeOutputStream(
3255 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3258 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3265 if (stdout.toString().contains("Error processing ")) {
3266 // j2s did not complete transpile
3267 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3268 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3269 println("IGNORING TRANSPILE ERRORS")
3270 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3272 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3277 inputs.dir("${jalviewDir}/${sourceDir}")
3278 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3279 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3283 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3285 def stdout = new ByteArrayOutputStream()
3286 def stderr = new ByteArrayOutputStream()
3288 def coreFile = file(jsfile)
3290 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3292 logOutFile.createNewFile()
3293 logOutFile.append(msg+"\n")
3295 def coreTop = file(prefixFile)
3296 def coreBottom = file(suffixFile)
3297 coreFile.getParentFile().mkdirs()
3298 coreFile.createNewFile()
3299 coreFile.write( coreTop.getText("UTF-8") )
3303 def t = f.getText("UTF-8")
3304 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3305 coreFile.append( t )
3307 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3309 logOutFile.append(msg+"\n")
3312 coreFile.append( coreBottom.getText("UTF-8") )
3314 msg = "Generating ${zjsfile}"
3316 logOutFile.append(msg+"\n")
3317 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3318 def logErrFOS = logOutFOS
3321 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3322 main = "com.google.javascript.jscomp.CommandLineRunner"
3323 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3324 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3327 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3329 logOutFile.append(msg+"\n")
3331 if (logOutConsole) {
3332 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3333 new org.apache.tools.ant.util.TeeOutputStream(
3337 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3338 new org.apache.tools.ant.util.TeeOutputStream(
3343 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3346 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3353 logOutFile.append(msg+"\n")
3357 task jalviewjsBuildAllCores {
3359 description "Build the core js lib closures listed in the classlists dir"
3360 dependsOn jalviewjsTranspile
3361 dependsOn jalviewjsTransferUnzipSwingJs
3363 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3364 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3365 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3366 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3367 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3368 def prefixFile = "${jsDir}/core/coretop2.js"
3369 def suffixFile = "${jsDir}/core/corebottom2.js"
3371 inputs.file prefixFile
3372 inputs.file suffixFile
3374 def classlistFiles = []
3375 // add the classlists found int the jalviewjs_classlists_dir
3376 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3378 def name = file.getName() - ".txt"
3385 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3386 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3387 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3389 jalviewjsCoreClasslists = []
3391 classlistFiles.each {
3394 def file = hash['file']
3395 if (! file.exists()) {
3396 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3397 return false // this is a "continue" in groovy .each closure
3399 def name = hash['name']
3401 name = file.getName() - ".txt"
3409 def list = fileTree(dir: j2sDir, includes: filelist)
3411 def jsfile = "${outputDir}/core${name}.js"
3412 def zjsfile = "${outputDir}/core${name}.z.js"
3414 jalviewjsCoreClasslists += [
3423 outputs.file(jsfile)
3424 outputs.file(zjsfile)
3427 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3428 def stevesoftClasslistName = "_stevesoft"
3429 def stevesoftClasslist = [
3430 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3431 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3432 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3433 'name': stevesoftClasslistName
3435 jalviewjsCoreClasslists += stevesoftClasslist
3436 inputs.files(stevesoftClasslist['list'])
3437 outputs.file(stevesoftClasslist['jsfile'])
3438 outputs.file(stevesoftClasslist['zjsfile'])
3441 def allClasslistName = "_all"
3442 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3443 allJsFiles += fileTree(
3447 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3448 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3449 "**/org/jmol/export/JSExporter.js"
3452 allJsFiles += fileTree(
3456 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3457 "**/sun/misc/Unsafe.js",
3458 "**/swingjs/jquery/jquery-editable-select.js",
3459 "**/swingjs/jquery/j2sComboBox.js",
3460 "**/sun/misc/FloatingDecimal.js"
3463 def allClasslist = [
3464 'jsfile': "${outputDir}/core${allClasslistName}.js",
3465 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3467 'name': allClasslistName
3469 // not including this version of "all" core at the moment
3470 //jalviewjsCoreClasslists += allClasslist
3471 inputs.files(allClasslist['list'])
3472 outputs.file(allClasslist['jsfile'])
3473 outputs.file(allClasslist['zjsfile'])
3476 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3477 logOutFile.getParentFile().mkdirs()
3478 logOutFile.createNewFile()
3479 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3481 jalviewjsCoreClasslists.each {
3482 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3489 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3492 into file(outputFile).getParentFile()
3493 rename { filename ->
3494 if (filename.equals(inputFile.getName())) {
3495 return file(outputFile).getName()
3499 filter(ReplaceTokens,
3503 'MAIN': '"'+main_class+'"',
3505 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3506 'COREKEY': jalviewjs_core_key,
3507 'CORENAME': coreName
3514 task jalviewjsPublishCoreTemplates {
3515 dependsOn jalviewjsBuildAllCores
3516 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3517 def inputFile = file(inputFileName)
3518 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3520 def outputFiles = []
3521 jalviewjsCoreClasslists.each { cl ->
3522 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3523 cl['outputfile'] = outputFile
3524 outputFiles += outputFile
3528 jalviewjsCoreClasslists.each { cl ->
3529 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3532 inputs.file(inputFile)
3533 outputs.files(outputFiles)
3537 task jalviewjsSyncCore (type: Sync) {
3538 dependsOn jalviewjsBuildAllCores
3539 dependsOn jalviewjsPublishCoreTemplates
3540 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3541 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3545 def outputFiles = []
3546 rename { filename ->
3547 outputFiles += "${outputDir}/${filename}"
3553 outputs.files outputFiles
3554 inputs.files inputFiles
3558 // this Copy version of TransferSiteJs will delete anything else in the target dir
3559 task jalviewjsCopyTransferSiteJs(type: Copy) {
3560 dependsOn jalviewjsTranspile
3561 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3562 into "${jalviewDir}/${jalviewjsSiteDir}"
3566 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3567 task jalviewjsSyncTransferSiteJs(type: Sync) {
3568 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3570 into "${jalviewDir}/${jalviewjsSiteDir}"
3577 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3578 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3579 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3580 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3582 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3583 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3584 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3585 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3588 task jalviewjsPrepareSite {
3590 description "Prepares the website folder including unzipping files and copying resources"
3591 dependsOn jalviewjsSyncAllLibs
3592 dependsOn jalviewjsSyncResources
3593 dependsOn jalviewjsSyncSiteResources
3594 dependsOn jalviewjsSyncBuildProperties
3595 dependsOn jalviewjsSyncCore
3599 task jalviewjsBuildSite {
3601 description "Builds the whole website including transpiled code"
3602 dependsOn jalviewjsCopyTransferSiteJs
3603 dependsOn jalviewjsPrepareSite
3607 task cleanJalviewjsTransferSite {
3609 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3610 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3611 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3612 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3617 task cleanJalviewjsSite {
3618 dependsOn cleanJalviewjsTransferSite
3620 delete "${jalviewDir}/${jalviewjsSiteDir}"
3625 task jalviewjsSiteTar(type: Tar) {
3627 description "Creates a tar.gz file for the website"
3628 dependsOn jalviewjsBuildSite
3629 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3630 archiveFileName = outputFilename
3632 compression Compression.GZIP
3634 from "${jalviewDir}/${jalviewjsSiteDir}"
3635 into jalviewjs_site_dir // this is inside the tar file
3637 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3641 task jalviewjsServer {
3643 def filename = "jalviewjsTest.html"
3644 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3645 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3650 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3651 factory = f.newInstance()
3652 } catch (ClassNotFoundException e) {
3653 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3655 def port = Integer.valueOf(jalviewjs_server_port)
3660 while(port < start+1000 && !running) {
3662 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3663 jalviewjsServer = factory.start(doc_root, port)
3665 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3666 println("SERVER STARTED with document root ${doc_root}.")
3667 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3668 println("For debug: "+url+"?j2sdebug")
3669 println("For verbose: "+url+"?j2sverbose")
3670 } catch (Exception e) {
3675 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3676 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3677 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3679 jalviewjsCoreClasslists.each { cl ->
3680 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3682 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3684 println("For core ${cl.name}: "+urlcore)
3687 file(htmlFile).text = htmlText
3690 outputs.file(htmlFile)
3691 outputs.upToDateWhen({false})
3695 task cleanJalviewjsAll {
3697 description "Delete all configuration and build artifacts to do with JalviewJS build"
3698 dependsOn cleanJalviewjsSite
3699 dependsOn jalviewjsEclipsePaths
3702 delete "${jalviewDir}/${jalviewjsBuildDir}"
3703 delete "${jalviewDir}/${eclipse_bin_dir}"
3704 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3705 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3707 delete jalviewjsJ2sAltSettingsFileName
3710 outputs.upToDateWhen( { false } )
3714 task jalviewjsIDE_checkJ2sPlugin {
3715 group "00 JalviewJS in Eclipse"
3716 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3719 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3720 def j2sPluginFile = file(j2sPlugin)
3721 def eclipseHome = System.properties["eclipse.home.location"]
3722 if (eclipseHome == null || ! IN_ECLIPSE) {
3723 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3725 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3726 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3727 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3728 eclipseJ2sPluginDirs += altPluginsDir
3730 def foundPlugin = false
3731 def j2sPluginFileName = j2sPluginFile.getName()
3732 def eclipseJ2sPlugin
3733 def eclipseJ2sPluginFile
3734 eclipseJ2sPluginDirs.any { dir ->
3735 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3736 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3737 if (eclipseJ2sPluginFile.exists()) {
3743 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3744 System.err.println(msg)
3745 throw new StopExecutionException(msg)
3748 def digest = MessageDigest.getInstance("MD5")
3750 digest.update(j2sPluginFile.text.bytes)
3751 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3753 digest.update(eclipseJ2sPluginFile.text.bytes)
3754 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3756 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3757 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3758 System.err.println(msg)
3759 throw new StopExecutionException(msg)
3761 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3767 task jalviewjsIDE_copyJ2sPlugin {
3768 group "00 JalviewJS in Eclipse"
3769 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3772 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3773 def j2sPluginFile = file(j2sPlugin)
3774 def eclipseHome = System.properties["eclipse.home.location"]
3775 if (eclipseHome == null || ! IN_ECLIPSE) {
3776 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3778 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3779 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3780 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3781 System.err.println(msg)
3784 eclipseJ2sPluginFile.getParentFile().mkdirs()
3785 into eclipseJ2sPluginFile.getParent()
3791 task jalviewjsIDE_j2sFile {
3792 group "00 JalviewJS in Eclipse"
3793 description "Creates the .j2s file"
3794 dependsOn jalviewjsCreateJ2sSettings
3798 task jalviewjsIDE_SyncCore {
3799 group "00 JalviewJS in Eclipse"
3800 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3801 dependsOn jalviewjsSyncCore
3805 task jalviewjsIDE_SyncSiteAll {
3806 dependsOn jalviewjsSyncAllLibs
3807 dependsOn jalviewjsSyncResources
3808 dependsOn jalviewjsSyncSiteResources
3809 dependsOn jalviewjsSyncBuildProperties
3813 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3816 task jalviewjsIDE_PrepareSite {
3817 group "00 JalviewJS in Eclipse"
3818 description "Sync libs and resources to site dir, but not closure cores"
3820 dependsOn jalviewjsIDE_SyncSiteAll
3821 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3825 task jalviewjsIDE_AssembleSite {
3826 group "00 JalviewJS in Eclipse"
3827 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3828 dependsOn jalviewjsPrepareSite
3832 task jalviewjsIDE_SiteClean {
3833 group "00 JalviewJS in Eclipse"
3834 description "Deletes the Eclipse transpiled site"
3835 dependsOn cleanJalviewjsSite
3839 task jalviewjsIDE_Server {
3840 group "00 JalviewJS in Eclipse"
3841 description "Starts a webserver on localhost to test the website"
3842 dependsOn jalviewjsServer
3846 // buildship runs this at import or gradle refresh
3847 task eclipseSynchronizationTask {
3848 //dependsOn eclipseSetup
3849 dependsOn createBuildProperties
3851 dependsOn jalviewjsIDE_j2sFile
3852 dependsOn jalviewjsIDE_checkJ2sPlugin
3853 dependsOn jalviewjsIDE_PrepareSite
3858 // buildship runs this at build time or project refresh
3859 task eclipseAutoBuildTask {
3860 //dependsOn jalviewjsIDE_checkJ2sPlugin
3861 //dependsOn jalviewjsIDE_PrepareSite
3867 description "Build the site"
3868 dependsOn jalviewjsBuildSite