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 groovy.transform.ExternalizeMethods
13 import groovy.util.XmlParser
14 import groovy.xml.XmlUtil
15 import groovy.json.JsonBuilder
16 import com.vladsch.flexmark.util.ast.Node
17 import com.vladsch.flexmark.html.HtmlRenderer
18 import com.vladsch.flexmark.parser.Parser
19 import com.vladsch.flexmark.util.data.MutableDataSet
20 import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension
21 import com.vladsch.flexmark.ext.tables.TablesExtension
22 import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension
23 import com.vladsch.flexmark.ext.autolink.AutolinkExtension
24 import com.vladsch.flexmark.ext.anchorlink.AnchorLinkExtension
25 import com.vladsch.flexmark.ext.toc.TocExtension
26 import com.google.common.hash.HashCode
27 import com.google.common.hash.Hashing
28 import com.google.common.io.Files
29 import org.jsoup.Jsoup
30 import org.jsoup.nodes.Element
38 classpath "com.vladsch.flexmark:flexmark-all:0.62.0"
39 classpath "org.jsoup:jsoup:1.14.3"
48 id "com.diffplug.gradle.spotless" version "3.28.0"
49 id 'com.github.johnrengelman.shadow' version '4.0.3'
50 id 'com.install4j.gradle' version '9.0.6'
51 id 'com.dorongold.task-tree' version '2.1.0' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
52 id 'com.palantir.git-version' version '0.13.0' apply false
63 // in ext the values are cast to Object. Ensure string values are cast as String (and not GStringImpl) for later use
64 def string(Object o) {
65 return o == null ? "" : o.toString()
68 def overrideProperties(String propsFileName, boolean output = false) {
69 if (propsFileName == null) {
72 def propsFile = file(propsFileName)
73 if (propsFile != null && propsFile.exists()) {
74 println("Using properties from file '${propsFileName}'")
76 def p = new Properties()
77 def localPropsFIS = new FileInputStream(propsFile)
83 if (project.hasProperty(key)) {
84 oldval = project.findProperty(key)
85 project.setProperty(key, val)
87 println("Overriding property '${key}' ('${oldval}') with ${file(propsFile).getName()} value '${val}'")
90 ext.setProperty(key, val)
92 println("Setting ext property '${key}' with ${file(propsFile).getName()}s value '${val}'")
96 } catch (Exception e) {
97 println("Exception reading local.properties")
104 jalviewDirAbsolutePath = file(jalviewDir).getAbsolutePath()
105 jalviewDirRelativePath = jalviewDir
108 getdownChannelName = CHANNEL.toLowerCase()
109 // default to "default". Currently only has different cosmetics for "develop", "release", "default"
110 propertiesChannelName = ["develop", "release", "test-release", "jalviewjs", "jalviewjs-release" ].contains(getdownChannelName) ? getdownChannelName : "default"
111 // Import channel_properties
112 channelDir = string("${jalviewDir}/${channel_properties_dir}/${propertiesChannelName}")
113 channelGradleProperties = string("${channelDir}/channel_gradle.properties")
114 channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}")
115 overrideProperties(channelGradleProperties, false)
116 // local build environment properties
117 // can be "projectDir/local.properties"
118 overrideProperties("${projectDir}/local.properties", true)
119 // or "../projectDir_local.properties"
120 overrideProperties(projectDir.getParent() + "/" + projectDir.getName() + "_local.properties", true)
123 // Import releaseProps from the RELEASE file
124 // or a file specified via JALVIEW_RELEASE_FILE if defined
125 // Expect jalview.version and target release branch in jalview.release
126 releaseProps = new Properties();
127 def releasePropFile = findProperty("JALVIEW_RELEASE_FILE");
128 def defaultReleasePropFile = "${jalviewDirAbsolutePath}/RELEASE";
130 (new File(releasePropFile!=null ? releasePropFile : defaultReleasePropFile)).withInputStream {
131 releaseProps.load(it)
133 } catch (Exception fileLoadError) {
134 throw new Error("Couldn't load release properties file "+(releasePropFile==null ? defaultReleasePropFile : "from custom location: releasePropFile"),fileLoadError);
137 // Set JALVIEW_VERSION if it is not already set
138 if (findProperty("JALVIEW_VERSION")==null || "".equals(JALVIEW_VERSION)) {
139 JALVIEW_VERSION = releaseProps.get("jalview.version")
141 println("JALVIEW_VERSION is set to '${JALVIEW_VERSION}'")
143 // this property set when running Eclipse headlessly
144 j2sHeadlessBuildProperty = string("net.sf.j2s.core.headlessbuild")
145 // this property set by Eclipse
146 eclipseApplicationProperty = string("eclipse.application")
147 // CHECK IF RUNNING FROM WITHIN ECLIPSE
148 def eclipseApplicationPropertyVal = System.properties[eclipseApplicationProperty]
149 IN_ECLIPSE = eclipseApplicationPropertyVal != null && eclipseApplicationPropertyVal.startsWith("org.eclipse.ui.")
150 // BUT WITHOUT THE HEADLESS BUILD PROPERTY SET
151 if (System.properties[j2sHeadlessBuildProperty].equals("true")) {
152 println("Setting IN_ECLIPSE to ${IN_ECLIPSE} as System.properties['${j2sHeadlessBuildProperty}'] == '${System.properties[j2sHeadlessBuildProperty]}'")
156 println("WITHIN ECLIPSE IDE")
158 println("HEADLESS BUILD")
161 J2S_ENABLED = (project.hasProperty('j2s.compiler.status') && project['j2s.compiler.status'] != null && project['j2s.compiler.status'] == "enable")
163 println("J2S ENABLED")
166 System.properties.sort { it.key }.each {
167 key, val -> println("SYSTEM PROPERTY ${key}='${val}'")
170 if (false && IN_ECLIPSE) {
171 jalviewDir = jalviewDirAbsolutePath
176 buildDate = new Date().format("yyyyMMdd")
179 bareSourceDir = string(source_dir)
180 sourceDir = string("${jalviewDir}/${bareSourceDir}")
181 resourceDir = string("${jalviewDir}/${resource_dir}")
182 bareTestSourceDir = string(test_source_dir)
183 testDir = string("${jalviewDir}/${bareTestSourceDir}")
185 classesDir = string("${jalviewDir}/${classes_dir}")
188 useClover = clover.equals("true")
189 cloverBuildDir = "${buildDir}/clover"
190 cloverInstrDir = file("${cloverBuildDir}/clover-instr")
191 cloverClassesDir = file("${cloverBuildDir}/clover-classes")
192 cloverReportDir = file("${buildDir}/reports/clover")
193 cloverTestInstrDir = file("${cloverBuildDir}/clover-test-instr")
194 cloverTestClassesDir = file("${cloverBuildDir}/clover-test-classes")
195 //cloverTestClassesDir = cloverClassesDir
196 cloverDb = string("${cloverBuildDir}/clover.db")
198 testSourceDir = useClover ? cloverTestInstrDir : testDir
199 testClassesDir = useClover ? cloverTestClassesDir : "${jalviewDir}/${test_output_dir}"
201 getdownChannelDir = string("${getdown_website_dir}/${propertiesChannelName}")
202 getdownAppBaseDir = string("${jalviewDir}/${getdownChannelDir}/${JAVA_VERSION}")
203 getdownArchiveDir = string("${jalviewDir}/${getdown_archive_dir}")
204 getdownFullArchiveDir = null
205 getdownTextLines = []
206 getdownLaunchJvl = null
207 getdownVersionLaunchJvl = null
209 buildProperties = null
211 // the following values might be overridden by the CHANNEL switch
212 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
213 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
214 getdownArchiveAppBase = getdown_archive_base
215 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher}")
216 getdownAppDistDir = getdown_app_dir_alt
217 getdownImagesDir = string("${jalviewDir}/${getdown_images_dir}")
218 getdownSetAppBaseProperty = false // whether to pass the appbase and appdistdir to the application
219 reportRsyncCommand = false
220 jvlChannelName = CHANNEL.toLowerCase()
221 install4jSuffix = CHANNEL.substring(0, 1).toUpperCase() + CHANNEL.substring(1).toLowerCase(); // BUILD -> Build
222 install4jDMGDSStore = "${install4j_images_dir}/${install4j_dmg_ds_store}"
223 install4jDMGBackgroundImage = "${install4j_images_dir}/${install4j_dmg_background}"
224 install4jInstallerName = "${jalview_name} Non-Release Installer"
225 install4jExecutableName = install4j_executable_name
226 install4jExtraScheme = "jalviewx"
227 install4jMacIconsFile = string("${install4j_images_dir}/${install4j_mac_icons_file}")
228 install4jWindowsIconsFile = string("${install4j_images_dir}/${install4j_windows_icons_file}")
229 install4jPngIconFile = string("${install4j_images_dir}/${install4j_png_icon_file}")
230 install4jBackground = string("${install4j_images_dir}/${install4j_background}")
231 install4jBuildDir = "${install4j_build_dir}/${JAVA_VERSION}"
232 install4jCheckSums = true
234 applicationName = "${jalview_name}"
238 // TODO: get bamboo build artifact URL for getdown artifacts
239 getdown_channel_base = bamboo_channelbase
240 getdownChannelName = string("${bamboo_planKey}/${JAVA_VERSION}")
241 getdownAppBase = string("${bamboo_channelbase}/${bamboo_planKey}${bamboo_getdown_channel_suffix}/${JAVA_VERSION}")
242 jvlChannelName += "_${getdownChannelName}"
243 // automatically add the test group Not-bamboo for exclusion
244 if ("".equals(testng_excluded_groups)) {
245 testng_excluded_groups = "Not-bamboo"
247 install4jExtraScheme = "jalviewb"
250 case [ "RELEASE", "JALVIEWJS-RELEASE" ]:
251 getdownAppDistDir = getdown_app_dir_release
252 getdownSetAppBaseProperty = true
253 reportRsyncCommand = true
255 install4jInstallerName = "${jalview_name} Installer"
259 getdownChannelName = CHANNEL.toLowerCase()+"/${JALVIEW_VERSION}"
260 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
261 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
262 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
263 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
265 package_dir = string("${ARCHIVEDIR}/${package_dir}")
266 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
269 reportRsyncCommand = true
270 install4jExtraScheme = "jalviewa"
274 getdownChannelName = string("archive/${JALVIEW_VERSION}")
275 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
276 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
277 if (!file("${ARCHIVEDIR}/${package_dir}").exists()) {
278 throw new GradleException("Must provide an ARCHIVEDIR value to produce an archive distribution")
280 package_dir = string("${ARCHIVEDIR}/${package_dir}")
281 buildProperties = string("${ARCHIVEDIR}/${classes_dir}/${build_properties_file}")
284 reportRsyncCommand = true
285 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
286 install4jSuffix = "Archive"
287 install4jExtraScheme = "jalviewa"
291 reportRsyncCommand = true
292 getdownSetAppBaseProperty = true
293 // DEVELOP-RELEASE is usually associated with a Jalview release series so set the version
294 JALVIEW_VERSION=JALVIEW_VERSION+"-d${buildDate}"
296 install4jSuffix = "Develop"
297 install4jExtraScheme = "jalviewd"
298 install4jInstallerName = "${jalview_name} Develop Installer"
302 reportRsyncCommand = true
303 getdownSetAppBaseProperty = true
304 // Don't ignore transpile errors for release build
305 if (jalviewjs_ignore_transpile_errors.equals("true")) {
306 jalviewjs_ignore_transpile_errors = "false"
307 println("Setting jalviewjs_ignore_transpile_errors to 'false'")
309 JALVIEW_VERSION = JALVIEW_VERSION+"-test"
310 install4jSuffix = "Test"
311 install4jExtraScheme = "jalviewt"
312 install4jInstallerName = "${jalview_name} Test Installer"
315 case ~/^SCRATCH(|-[-\w]*)$/:
316 getdownChannelName = CHANNEL
317 JALVIEW_VERSION = JALVIEW_VERSION+"-"+CHANNEL
319 getdownDir = string("${getdownChannelName}/${JAVA_VERSION}")
320 getdownAppBase = string("${getdown_channel_base}/${getdownDir}")
321 reportRsyncCommand = true
322 install4jSuffix = "Scratch"
326 if (!file("${LOCALDIR}").exists()) {
327 throw new GradleException("Must provide a LOCALDIR value to produce a local distribution")
329 getdownAppBase = file(file("${LOCALDIR}").getAbsolutePath()).toURI().toString()
330 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
332 JALVIEW_VERSION = "TEST"
333 install4jSuffix = "Test-Local"
334 install4jExtraScheme = "jalviewt"
335 install4jInstallerName = "${jalview_name} Test Installer"
338 case [ "LOCAL", "JALVIEWJS" ]:
339 JALVIEW_VERSION = "TEST"
340 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
341 getdownArchiveAppBase = file("${jalviewDir}/${getdown_archive_dir}").toURI().toString()
342 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
343 install4jExtraScheme = "jalviewl"
344 install4jCheckSums = false
347 default: // something wrong specified
348 throw new GradleException("CHANNEL must be one of BUILD, RELEASE, ARCHIVE, DEVELOP, TEST-RELEASE, SCRATCH-..., LOCAL [default]")
352 JALVIEW_VERSION_UNDERSCORES = JALVIEW_VERSION.replaceAll("\\.", "_")
353 hugoDataJsonFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_data_installers_dir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
354 hugoArchiveMdFile = file("${jalviewDir}/${hugo_build_dir}/${hugo_version_archive_dir}/Version-${JALVIEW_VERSION_UNDERSCORES}/_index.md")
355 // override getdownAppBase if requested
356 if (findProperty("getdown_appbase_override") != null) {
357 // revert to LOCAL if empty string
358 if (string(getdown_appbase_override) == "") {
359 getdownAppBase = file(getdownAppBaseDir).toURI().toString()
360 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
361 } else if (string(getdown_appbase_override).startsWith("file://")) {
362 getdownAppBase = string(getdown_appbase_override)
363 getdownLauncher = string("${jalviewDir}/${getdown_lib_dir}/${getdown_launcher_local}")
365 getdownAppBase = string(getdown_appbase_override)
367 println("Overriding getdown appbase with '${getdownAppBase}'")
369 // sanitise file name for jalview launcher file for this channel
370 jvlChannelName = jvlChannelName.replaceAll("[^\\w\\-]+", "_")
371 // install4j application and folder names
372 if (install4jSuffix == "") {
373 install4jBundleId = "${install4j_bundle_id}"
374 install4jWinApplicationId = install4j_release_win_application_id
376 applicationName = "${jalview_name} ${install4jSuffix}"
377 install4jBundleId = "${install4j_bundle_id}-" + install4jSuffix.toLowerCase()
378 // add int hash of install4jSuffix to the last part of the application_id
379 def id = install4j_release_win_application_id
380 def idsplitreverse = id.split("-").reverse()
381 idsplitreverse[0] = idsplitreverse[0].toInteger() + install4jSuffix.hashCode()
382 install4jWinApplicationId = idsplitreverse.reverse().join("-")
384 // sanitise folder and id names
385 // install4jApplicationFolder = e.g. "Jalview Build"
386 install4jApplicationFolder = applicationName
387 .replaceAll("[\"'~:/\\\\\\s]", "_") // replace all awkward filename chars " ' ~ : / \
388 .replaceAll("_+", "_") // collapse __
389 install4jInternalId = applicationName
391 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
392 .replaceAll("_+", "") // collapse __
393 //.replaceAll("_*-_*", "-") // collapse _-_
394 install4jUnixApplicationFolder = applicationName
396 .replaceAll("[^\\w\\-\\.]", "_") // replace other non [alphanumeric,_,-,.]
397 .replaceAll("_+", "_") // collapse __
398 .replaceAll("_*-_*", "-") // collapse _-_
401 getdownWrapperLink = install4jUnixApplicationFolder // e.g. "jalview_local"
402 getdownAppDir = string("${getdownAppBaseDir}/${getdownAppDistDir}")
403 //getdownJ11libDir = "${getdownAppBaseDir}/${getdown_j11lib_dir}"
404 getdownResourceDir = string("${getdownAppBaseDir}/${getdown_resource_dir}")
405 getdownInstallDir = string("${getdownAppBaseDir}/${getdown_install_dir}")
406 getdownFilesDir = string("${jalviewDir}/${getdown_files_dir}/${JAVA_VERSION}/")
407 getdownFilesInstallDir = string("${getdownFilesDir}/${getdown_install_dir}")
408 /* compile without modules -- using classpath libraries
409 modules_compileClasspath = fileTree(dir: "${jalviewDir}/${j11modDir}", include: ["*.jar"])
410 modules_runtimeClasspath = modules_compileClasspath
416 apply plugin: "com.palantir.git-version"
417 def details = versionDetails()
418 gitHash = details.gitHash
419 gitBranch = details.branchName
420 } catch(org.gradle.api.internal.plugins.PluginApplicationException e) {
421 println("Not in a git repository. Using git values from RELEASE properties file.")
422 gitHash = releaseProps.getProperty("git.hash")
423 gitBranch = releaseProps.getProperty("git.branch")
424 } catch(java.lang.RuntimeException e1) {
425 throw new GradleException("Error with git-version plugin. Directory '.git' exists but versionDetails() cannot be found.")
428 println("Using a ${CHANNEL} profile.")
430 additional_compiler_args = []
431 // configure classpath/args for j8/j11 compilation
432 if (JAVA_VERSION.equals("1.8")) {
433 JAVA_INTEGER_VERSION = string("8")
436 libDistDir = j8libDir
437 compile_source_compatibility = 1.8
438 compile_target_compatibility = 1.8
439 // these are getdown.txt properties defined dependent on the JAVA_VERSION
440 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java8_min_version"))
441 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java8_max_version"))
442 // this property is assigned below and expanded to multiple lines in the getdown task
443 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java8_txt_multi_java_location"))
444 // this property is for the Java library used in eclipse
445 eclipseJavaRuntimeName = string("JavaSE-1.8")
446 } else if (JAVA_VERSION.equals("11")) {
447 JAVA_INTEGER_VERSION = string("11")
449 libDistDir = j11libDir
450 compile_source_compatibility = 11
451 compile_target_compatibility = 11
452 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
453 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
454 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
455 eclipseJavaRuntimeName = string("JavaSE-11")
456 /* compile without modules -- using classpath libraries
457 additional_compiler_args += [
458 '--module-path', modules_compileClasspath.asPath,
459 '--add-modules', j11modules
462 } else if (JAVA_VERSION.equals("17")) {
463 JAVA_INTEGER_VERSION = string("17")
465 libDistDir = j17libDir
466 compile_source_compatibility = 17
467 compile_target_compatibility = 17
468 getdownAltJavaMinVersion = string(findProperty("getdown_alt_java11_min_version"))
469 getdownAltJavaMaxVersion = string(findProperty("getdown_alt_java11_max_version"))
470 getdownAltMultiJavaLocation = string(findProperty("getdown_alt_java11_txt_multi_java_location"))
471 eclipseJavaRuntimeName = string("JavaSE-17")
472 /* compile without modules -- using classpath libraries
473 additional_compiler_args += [
474 '--module-path', modules_compileClasspath.asPath,
475 '--add-modules', j11modules
479 throw new GradleException("JAVA_VERSION=${JAVA_VERSION} not currently supported by Jalview")
484 JAVA_MIN_VERSION = JAVA_VERSION
485 JAVA_MAX_VERSION = JAVA_VERSION
486 def jreInstallsDir = string(jre_installs_dir)
487 if (jreInstallsDir.startsWith("~/")) {
488 jreInstallsDir = System.getProperty("user.home") + jreInstallsDir.substring(1)
490 macosJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-mac-x64/jre")
491 windowsJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-windows-x64/jre")
492 linuxJavaVMDir = string("${jreInstallsDir}/jre-${JAVA_INTEGER_VERSION}-linux-x64/jre")
493 macosJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_mac_x64.tar.gz")
494 windowsJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_windows_x64.tar.gz")
495 linuxJavaVMTgz = string("${jreInstallsDir}/tgz/jre_${JAVA_INTEGER_VERSION}_linux_x64.tar.gz")
496 install4jDir = string("${jalviewDir}/${install4j_utils_dir}")
497 install4jConfFileName = string("jalview-install4j-conf.install4j")
498 install4jConfFile = file("${install4jDir}/${install4jConfFileName}")
499 install4jHomeDir = install4j_home_dir
500 if (install4jHomeDir.startsWith("~/")) {
501 install4jHomeDir = System.getProperty("user.home") + install4jHomeDir.substring(1)
504 resourceBuildDir = string("${buildDir}/resources")
505 resourcesBuildDir = string("${resourceBuildDir}/resources_build")
506 helpBuildDir = string("${resourceBuildDir}/help_build")
507 docBuildDir = string("${resourceBuildDir}/doc_build")
509 if (buildProperties == null) {
510 buildProperties = string("${resourcesBuildDir}/${build_properties_file}")
512 buildingHTML = string("${jalviewDir}/${doc_dir}/building.html")
513 helpParentDir = string("${jalviewDir}/${help_parent_dir}")
514 helpSourceDir = string("${helpParentDir}/${help_dir}")
515 helpFile = string("${helpBuildDir}/${help_dir}/help.jhm")
518 relativeBuildDir = file(jalviewDirAbsolutePath).toPath().relativize(buildDir.toPath())
519 jalviewjsBuildDir = string("${relativeBuildDir}/jalviewjs")
520 jalviewjsSiteDir = string("${jalviewjsBuildDir}/${jalviewjs_site_dir}")
522 jalviewjsTransferSiteJsDir = string(jalviewjsSiteDir)
524 jalviewjsTransferSiteJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_js")
526 jalviewjsTransferSiteLibDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_lib")
527 jalviewjsTransferSiteSwingJsDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_swingjs")
528 jalviewjsTransferSiteCoreDir = string("${jalviewjsBuildDir}/tmp/${jalviewjs_site_dir}_core")
529 jalviewjsJalviewCoreHtmlFile = string("")
530 jalviewjsJalviewCoreName = string(jalviewjs_core_name)
531 jalviewjsCoreClasslists = []
532 jalviewjsJalviewTemplateName = string(jalviewjs_name)
533 jalviewjsJ2sSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_settings}")
534 jalviewjsJ2sAltSettingsFileName = string("${jalviewDir}/${jalviewjs_j2s_alt_settings}")
535 jalviewjsJ2sProps = null
536 jalviewjsJ2sPlugin = jalviewjs_j2s_plugin
538 eclipseWorkspace = null
539 eclipseBinary = string("")
540 eclipseVersion = string("")
550 outputDir = file(classesDir)
554 srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
557 compileClasspath = files(sourceSets.main.java.outputDir)
558 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
560 runtimeClasspath = compileClasspath
561 runtimeClasspath += files(sourceSets.main.resources.srcDirs)
566 srcDirs cloverInstrDir
567 outputDir = cloverClassesDir
571 srcDirs = sourceSets.main.resources.srcDirs
574 compileClasspath = files( sourceSets.clover.java.outputDir )
575 //compileClasspath += files( testClassesDir )
576 compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
577 compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
578 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
580 runtimeClasspath = compileClasspath
585 srcDirs testSourceDir
586 outputDir = file(testClassesDir)
590 srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
593 compileClasspath = files( sourceSets.test.java.outputDir )
594 compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
595 compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
597 runtimeClasspath = compileClasspath
598 runtimeClasspath += files(sourceSets.test.resources.srcDirs)
604 // eclipse project and settings files creation, also used by buildship
607 name = eclipse_project_name
609 natures 'org.eclipse.jdt.core.javanature',
610 'org.eclipse.jdt.groovy.core.groovyNature',
611 'org.eclipse.buildship.core.gradleprojectnature'
613 buildCommand 'org.eclipse.jdt.core.javabuilder'
614 buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
618 //defaultOutputDir = sourceSets.main.java.outputDir
619 configurations.each{ c->
620 if (c.isCanBeResolved()) {
621 minusConfigurations += [c]
625 plusConfigurations = [ ]
629 def removeTheseToo = []
630 HashMap<String, Boolean> alreadyAddedSrcPath = new HashMap<>();
631 cp.entries.each { entry ->
632 // This conditional removes all src classpathentries that a) have already been added or b) aren't "src" or "test".
633 // e.g. this removes the resources dir being copied into bin/main, bin/test AND bin/clover
634 // we add the resources and help/help dirs in as libs afterwards (see below)
635 if (entry.kind == 'src') {
636 if (alreadyAddedSrcPath.getAt(entry.path) || !(entry.path == bareSourceDir || entry.path == bareTestSourceDir)) {
637 removeTheseToo += entry
639 alreadyAddedSrcPath.putAt(entry.path, true)
644 cp.entries.removeAll(removeTheseToo)
646 //cp.entries += new Output("${eclipse_bin_dir}/main")
647 if (file(helpParentDir).isDirectory()) {
648 cp.entries += new Library(fileReference(helpParentDir))
650 if (file(resourceDir).isDirectory()) {
651 cp.entries += new Library(fileReference(resourceDir))
654 HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
656 sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
657 //don't want to add outputDir as eclipse is using its own output dir in bin/main
658 if (it.isDirectory() || ! it.exists()) {
659 // don't add dirs to classpath, especially if they don't exist
660 return false // groovy "continue" in .any closure
662 def itPath = it.toString()
663 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
664 // make relative path
665 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
667 if (alreadyAddedLibPath.get(itPath)) {
668 //println("Not adding duplicate entry "+itPath)
670 //println("Adding entry "+itPath)
671 cp.entries += new Library(fileReference(itPath))
672 alreadyAddedLibPath.put(itPath, true)
676 sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
677 //no longer want to add outputDir as eclipse is using its own output dir in bin/main
678 if (it.isDirectory() || ! it.exists()) {
679 // don't add dirs to classpath
680 return false // groovy "continue" in .any closure
683 def itPath = it.toString()
684 if (itPath.startsWith("${jalviewDirAbsolutePath}/")) {
685 itPath = itPath.substring(jalviewDirAbsolutePath.length()+1)
687 if (alreadyAddedLibPath.get(itPath)) {
690 def lib = new Library(fileReference(itPath))
691 lib.entryAttributes["test"] = "true"
693 alreadyAddedLibPath.put(itPath, true)
701 containers 'org.eclipse.buildship.core.gradleclasspathcontainer'
706 // for the IDE, use java 11 compatibility
707 sourceCompatibility = compile_source_compatibility
708 targetCompatibility = compile_target_compatibility
709 javaRuntimeName = eclipseJavaRuntimeName
711 // add in jalview project specific properties/preferences into eclipse core preferences
713 withProperties { props ->
714 def jalview_prefs = new Properties()
715 def ins = new FileInputStream("${jalviewDirAbsolutePath}/${eclipse_extra_jdt_prefs_file}")
716 jalview_prefs.load(ins)
718 jalview_prefs.forEach { t, v ->
719 if (props.getAt(t) == null) {
723 // codestyle file -- overrides previous formatter prefs
724 def csFile = file("${jalviewDirAbsolutePath}/${eclipse_codestyle_file}")
725 if (csFile.exists()) {
726 XmlParser parser = new XmlParser()
727 def profiles = parser.parse(csFile)
728 def profile = profiles.'profile'.find { p -> (p.'@kind' == "CodeFormatterProfile" && p.'@name' == "Jalview") }
729 if (profile != null) {
730 profile.'setting'.each { s ->
732 def value = s.'@value'
733 if (id != null && value != null) {
734 props.putAt(id, value)
745 // Don't want these to be activated if in headless build
746 synchronizationTasks "eclipseSynchronizationTask"
747 //autoBuildTasks "eclipseAutoBuildTask"
753 /* hack to change eclipse prefs in .settings files other than org.eclipse.jdt.core.prefs */
754 // Class to allow updating arbitrary properties files
755 class PropertiesFile extends PropertiesPersistableConfigurationObject {
756 public PropertiesFile(PropertiesTransformer t) { super(t); }
757 @Override protected void load(Properties properties) { }
758 @Override protected void store(Properties properties) { }
759 @Override protected String getDefaultResourceName() { return ""; }
760 // This is necessary, because PropertiesPersistableConfigurationObject fails
761 // if no default properties file exists.
762 @Override public void loadDefaults() { load(new StringBufferInputStream("")); }
765 // Task to update arbitrary properties files (set outputFile)
766 class PropertiesFileTask extends PropertiesGeneratorTask<PropertiesFile> {
767 private final PropertiesFileContentMerger file;
768 public PropertiesFileTask() { file = new PropertiesFileContentMerger(getTransformer()); }
769 protected PropertiesFile create() { return new PropertiesFile(getTransformer()); }
770 protected void configure(PropertiesFile props) {
771 file.getBeforeMerged().execute(props); file.getWhenMerged().execute(props);
773 public void file(Closure closure) { ConfigureUtil.configure(closure, file); }
776 task eclipseUIPreferences(type: PropertiesFileTask) {
777 description = "Generate Eclipse additional settings"
778 def filename = "org.eclipse.jdt.ui.prefs"
779 outputFile = "$projectDir/.settings/${filename}" as File
782 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
787 task eclipseGroovyCorePreferences(type: PropertiesFileTask) {
788 description = "Generate Eclipse additional settings"
789 def filename = "org.eclipse.jdt.groovy.core.prefs"
790 outputFile = "$projectDir/.settings/${filename}" as File
793 it.load new FileInputStream("$projectDir/utils/eclipse/${filename}" as String)
798 task eclipseAllPreferences {
800 dependsOn eclipseUIPreferences
801 dependsOn eclipseGroovyCorePreferences
804 eclipseUIPreferences.mustRunAfter eclipseJdt
805 eclipseGroovyCorePreferences.mustRunAfter eclipseJdt
807 /* end of eclipse preferences hack */
815 delete cloverBuildDir
816 delete cloverReportDir
821 task cloverInstrJava(type: JavaExec) {
822 group = "Verification"
823 description = "Create clover instrumented source java files"
825 dependsOn cleanClover
827 inputs.files(sourceSets.main.allJava)
828 outputs.dir(cloverInstrDir)
830 //classpath = fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
831 classpath = sourceSets.clover.compileClasspath
832 main = "com.atlassian.clover.CloverInstr"
840 cloverInstrDir.getPath(),
842 def srcFiles = sourceSets.main.allJava.files
845 { file -> file.absolutePath }
848 args argsList.toArray()
851 delete cloverInstrDir
852 println("Clover: About to instrument "+srcFiles.size() +" files")
857 task cloverInstrTests(type: JavaExec) {
858 group = "Verification"
859 description = "Create clover instrumented source test files"
861 dependsOn cleanClover
863 inputs.files(testDir)
864 outputs.dir(cloverTestInstrDir)
866 classpath = sourceSets.clover.compileClasspath
867 main = "com.atlassian.clover.CloverInstr"
877 cloverTestInstrDir.getPath(),
879 args argsList.toArray()
882 delete cloverTestInstrDir
883 println("Clover: About to instrument test files")
889 group = "Verification"
890 description = "Create clover instrumented all source files"
892 dependsOn cloverInstrJava
893 dependsOn cloverInstrTests
897 cloverClasses.dependsOn cloverInstr
900 task cloverConsoleReport(type: JavaExec) {
901 group = "Verification"
902 description = "Creates clover console report"
905 file(cloverDb).exists()
908 inputs.dir cloverClassesDir
910 classpath = sourceSets.clover.runtimeClasspath
911 main = "com.atlassian.clover.reporters.console.ConsoleReporter"
913 if (cloverreport_mem.length() > 0) {
914 maxHeapSize = cloverreport_mem
916 if (cloverreport_jvmargs.length() > 0) {
917 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
927 args argsList.toArray()
931 task cloverHtmlReport(type: JavaExec) {
932 group = "Verification"
933 description = "Creates clover HTML report"
936 file(cloverDb).exists()
939 def cloverHtmlDir = cloverReportDir
940 inputs.dir cloverClassesDir
941 outputs.dir cloverHtmlDir
943 classpath = sourceSets.clover.runtimeClasspath
944 main = "com.atlassian.clover.reporters.html.HtmlReporter"
946 if (cloverreport_mem.length() > 0) {
947 maxHeapSize = cloverreport_mem
949 if (cloverreport_jvmargs.length() > 0) {
950 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
961 if (cloverreport_html_options.length() > 0) {
962 argsList += cloverreport_html_options.split(" ")
965 args argsList.toArray()
969 task cloverXmlReport(type: JavaExec) {
970 group = "Verification"
971 description = "Creates clover XML report"
974 file(cloverDb).exists()
977 def cloverXmlFile = "${cloverReportDir}/clover.xml"
978 inputs.dir cloverClassesDir
979 outputs.file cloverXmlFile
981 classpath = sourceSets.clover.runtimeClasspath
982 main = "com.atlassian.clover.reporters.xml.XMLReporter"
984 if (cloverreport_mem.length() > 0) {
985 maxHeapSize = cloverreport_mem
987 if (cloverreport_jvmargs.length() > 0) {
988 jvmArgs Arrays.asList(cloverreport_jvmargs.split(" "))
999 if (cloverreport_xml_options.length() > 0) {
1000 argsList += cloverreport_xml_options.split(" ")
1003 args argsList.toArray()
1008 group = "Verification"
1009 description = "Creates clover reports"
1011 dependsOn cloverXmlReport
1012 dependsOn cloverHtmlReport
1019 sourceCompatibility = compile_source_compatibility
1020 targetCompatibility = compile_target_compatibility
1021 options.compilerArgs += additional_compiler_args
1022 print ("Setting target compatibility to "+targetCompatibility+"\n")
1024 //classpath += configurations.cloverRuntime
1030 // JBP->BS should the print statement in doFirst refer to compile_target_compatibility ?
1031 sourceCompatibility = compile_source_compatibility
1032 targetCompatibility = compile_target_compatibility
1033 options.compilerArgs = additional_compiler_args
1034 options.encoding = "UTF-8"
1036 print ("Setting target compatibility to "+compile_target_compatibility+"\n")
1043 sourceCompatibility = compile_source_compatibility
1044 targetCompatibility = compile_target_compatibility
1045 options.compilerArgs = additional_compiler_args
1047 print ("Setting target compatibility to "+targetCompatibility+"\n")
1054 delete sourceSets.main.java.outputDir
1060 dependsOn cleanClover
1062 delete sourceSets.test.java.outputDir
1067 // format is a string like date.format("dd MMMM yyyy")
1068 def getDate(format) {
1069 return date.format(format)
1073 def convertMdToHtml (FileTree mdFiles, File cssFile) {
1074 MutableDataSet options = new MutableDataSet()
1076 def extensions = new ArrayList<>()
1077 extensions.add(AnchorLinkExtension.create())
1078 extensions.add(AutolinkExtension.create())
1079 extensions.add(StrikethroughExtension.create())
1080 extensions.add(TaskListExtension.create())
1081 extensions.add(TablesExtension.create())
1082 extensions.add(TocExtension.create())
1084 options.set(Parser.EXTENSIONS, extensions)
1086 // set GFM table parsing options
1087 options.set(TablesExtension.WITH_CAPTION, false)
1088 options.set(TablesExtension.COLUMN_SPANS, false)
1089 options.set(TablesExtension.MIN_HEADER_ROWS, 1)
1090 options.set(TablesExtension.MAX_HEADER_ROWS, 1)
1091 options.set(TablesExtension.APPEND_MISSING_COLUMNS, true)
1092 options.set(TablesExtension.DISCARD_EXTRA_COLUMNS, true)
1093 options.set(TablesExtension.HEADER_SEPARATOR_COLUMN_MATCH, true)
1095 options.set(AnchorLinkExtension.ANCHORLINKS_SET_ID, false)
1096 options.set(AnchorLinkExtension.ANCHORLINKS_ANCHOR_CLASS, "anchor")
1097 options.set(AnchorLinkExtension.ANCHORLINKS_SET_NAME, true)
1098 options.set(AnchorLinkExtension.ANCHORLINKS_TEXT_PREFIX, "<span class=\"octicon octicon-link\"></span>")
1100 Parser parser = Parser.builder(options).build()
1101 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1103 mdFiles.each { mdFile ->
1104 // add table of contents
1105 def mdText = "[TOC]\n"+mdFile.text
1107 // grab the first top-level title
1109 def titleRegex = /(?m)^#(\s+|([^#]))(.*)/
1110 def matcher = mdText =~ titleRegex
1111 if (matcher.size() > 0) {
1112 // matcher[0][2] is the first character of the title if there wasn't any whitespace after the #
1113 title = (matcher[0][2] != null ? matcher[0][2] : "")+matcher[0][3]
1115 // or use the filename if none found
1116 if (title == null) {
1117 title = mdFile.getName()
1120 Node document = parser.parse(mdText)
1121 String htmlBody = renderer.render(document)
1122 def htmlText = '''<html>
1123 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1124 <html xmlns="http://www.w3.org/1999/xhtml">
1126 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1127 <meta http-equiv="Content-Style-Type" content="text/css" />
1128 <meta name="generator" content="flexmark" />
1130 htmlText += ((title != null) ? " <title>${title}</title>" : '' )
1132 <style type="text/css">code{white-space: pre;}</style>
1134 htmlText += ((cssFile != null) ? cssFile.text : '')
1135 htmlText += '''</head>
1138 htmlText += htmlBody
1144 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1145 def htmlFile = file(htmlFilePath)
1146 println("Creating ${htmlFilePath}")
1147 htmlFile.text = htmlText
1152 task copyDocs(type: Copy) {
1153 def inputDir = "${jalviewDir}/${doc_dir}"
1154 def outputDir = "${docBuildDir}/${doc_dir}"
1158 include('**/*.html')
1160 filter(ReplaceTokens,
1164 'Version-Rel': JALVIEW_VERSION,
1165 'Year-Rel': getDate("yyyy")
1172 exclude('**/*.html')
1177 inputs.dir(inputDir)
1178 outputs.dir(outputDir)
1182 task convertMdFiles {
1184 def mdFiles = fileTree(dir: docBuildDir, include: "**/*.md")
1185 def cssFile = file("${jalviewDir}/${flexmark_css}")
1188 convertMdToHtml(mdFiles, cssFile)
1191 inputs.files(mdFiles)
1192 inputs.file(cssFile)
1195 mdFiles.each { mdFile ->
1196 def htmlFilePath = mdFile.getPath().replaceAll(/\..*?$/, ".html")
1197 htmlFiles.add(file(htmlFilePath))
1199 outputs.files(htmlFiles)
1203 def hugoTemplateSubstitutions(String input, Map extras=null) {
1204 def replacements = [
1205 DATE: getDate("yyyy-MM-dd"),
1206 CHANNEL: propertiesChannelName,
1207 APPLICATION_NAME: applicationName,
1209 GIT_BRANCH: gitBranch,
1210 VERSION: JALVIEW_VERSION,
1211 JAVA_VERSION: JAVA_VERSION,
1212 VERSION_UNDERSCORES: JALVIEW_VERSION_UNDERSCORES,
1217 if (extras != null) {
1218 extras.each{ k, v ->
1219 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1222 replacements.each{ k, v ->
1223 output = output.replaceAll("__${k}__", ((v == null)?"":v))
1228 def mdFileComponents(File mdFile, def dateOnly=false) {
1231 if (mdFile.exists()) {
1232 def inFrontMatter = false
1233 def firstLine = true
1234 mdFile.eachLine { line ->
1235 if (line.matches("---")) {
1236 def prev = inFrontMatter
1237 inFrontMatter = firstLine
1238 if (inFrontMatter != prev)
1241 if (inFrontMatter) {
1243 if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
1244 map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
1245 } else if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
1246 map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
1247 } else if (m = line =~ /^channel:\s*(\S+)/) {
1248 map["channel"] = m[0][1]
1249 } else if (m = line =~ /^version:\s*(\S+)/) {
1250 map["version"] = m[0][1]
1251 } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
1252 map[ m[0][1] ] = m[0][2]
1254 if (dateOnly && map["date"] != null) {
1260 content += line+"\n"
1265 return dateOnly ? map["date"] : [map, content]
1268 task hugoTemplates {
1270 description "Create partially populated md pages for hugo website build"
1272 def hugoTemplatesDir = file("${jalviewDir}/${hugo_templates_dir}")
1273 def hugoBuildDir = "${jalviewDir}/${hugo_build_dir}"
1274 def templateFiles = fileTree(dir: hugoTemplatesDir)
1275 def releaseMdFile = file("${jalviewDir}/${releases_dir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1276 def whatsnewMdFile = file("${jalviewDir}/${whatsnew_dir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1277 def oldJvlFile = file("${jalviewDir}/${hugo_old_jvl}")
1278 def jalviewjsFile = file("${jalviewDir}/${hugo_jalviewjs}")
1281 // specific release template for version archive
1284 def givenDate = null
1285 def givenChannel = null
1286 def givenVersion = null
1287 if (CHANNEL == "RELEASE") {
1288 def (map, content) = mdFileComponents(releaseMdFile)
1289 givenDate = map.date
1290 givenChannel = map.channel
1291 givenVersion = map.version
1293 if (givenVersion != null && givenVersion != JALVIEW_VERSION) {
1294 throw new GradleException("'version' header (${givenVersion}) found in ${releaseMdFile} does not match JALVIEW_VERSION (${JALVIEW_VERSION})")
1297 if (whatsnewMdFile.exists())
1298 whatsnew = whatsnewMdFile.text
1301 def oldJvl = oldJvlFile.exists() ? oldJvlFile.collect{it} : []
1302 def jalviewjsLink = jalviewjsFile.exists() ? jalviewjsFile.collect{it} : []
1304 def changesHugo = null
1305 if (changes != null) {
1306 changesHugo = '<div class="release_notes">\n\n'
1307 def inSection = false
1308 changes.eachLine { line ->
1310 if (m = line =~ /^##([^#].*)$/) {
1312 changesHugo += "</div>\n\n"
1314 def section = m[0][1].trim()
1315 section = section.toLowerCase()
1316 section = section.replaceAll(/ +/, "_")
1317 section = section.replaceAll(/[^a-z0-9_\-]/, "")
1318 changesHugo += "<div class=\"${section}\">\n\n"
1320 } else if (m = line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
1321 def comment = m[0][2].trim()
1322 if (comment != "") {
1323 comment = comment.replaceAll('"', """)
1325 comment.eachMatch(/JAL-\d+/) { jal -> issuekeys += jal }
1326 def newline = m[0][1]
1327 if (comment.trim() != "")
1328 newline += "{{<comment>}}${comment}{{</comment>}} "
1329 newline += m[0][3].trim()
1330 if (issuekeys.size() > 0)
1331 newline += " {{< jal issue=\"${issuekeys.join(",")}\" alt=\"${comment}\" >}}"
1332 if (m[0][4] != null)
1337 changesHugo += line+"\n"
1340 changesHugo += "\n</div>\n\n"
1342 changesHugo += '</div>'
1345 templateFiles.each{ templateFile ->
1346 def newFileName = string(hugoTemplateSubstitutions(templateFile.getName()))
1347 def relPath = hugoTemplatesDir.toPath().relativize(templateFile.toPath()).getParent()
1348 def newRelPathName = hugoTemplateSubstitutions( relPath.toString() )
1350 def outPathName = string("${hugoBuildDir}/$newRelPathName")
1354 rename(templateFile.getName(), newFileName)
1358 def newFile = file("${outPathName}/${newFileName}".toString())
1359 def content = newFile.text
1360 newFile.text = hugoTemplateSubstitutions(content,
1363 CHANGES: changesHugo,
1364 DATE: givenDate == null ? "" : givenDate.format("yyyy-MM-dd"),
1365 DRAFT: givenDate == null ? "true" : "false",
1366 JALVIEWJSLINK: jalviewjsLink.contains(JALVIEW_VERSION) ? "true" : "false",
1367 JVL_HEADER: oldJvl.contains(JALVIEW_VERSION) ? "jvl: true" : ""
1374 inputs.file(oldJvlFile)
1375 inputs.dir(hugoTemplatesDir)
1376 inputs.property("JALVIEW_VERSION", { JALVIEW_VERSION })
1377 inputs.property("CHANNEL", { CHANNEL })
1380 def getMdDate(File mdFile) {
1381 return mdFileComponents(mdFile, true)
1384 def getMdSections(String content) {
1386 def sectionContent = ""
1387 def sectionName = null
1388 content.eachLine { line ->
1390 if (m = line =~ /^##([^#].*)$/) {
1391 if (sectionName != null) {
1392 sections[sectionName] = sectionContent
1396 sectionName = m[0][1].trim()
1397 sectionName = sectionName.toLowerCase()
1398 sectionName = sectionName.replaceAll(/ +/, "_")
1399 sectionName = sectionName.replaceAll(/[^a-z0-9_\-]/, "")
1400 } else if (sectionName != null) {
1401 sectionContent += line+"\n"
1404 if (sectionContent != null) {
1405 sections[sectionName] = sectionContent
1411 task copyHelp(type: Copy) {
1412 def inputDir = helpSourceDir
1413 def outputDir = "${helpBuildDir}/${help_dir}"
1417 include('**/*.html')
1421 filter(ReplaceTokens,
1425 'Version-Rel': JALVIEW_VERSION,
1426 'Year-Rel': getDate("yyyy")
1433 exclude('**/*.html')
1440 inputs.dir(inputDir)
1441 outputs.files(helpFile)
1442 outputs.dir(outputDir)
1446 task releasesTemplates {
1448 description "Recreate whatsNew.html and releases.html from markdown files and templates in help"
1452 def releasesTemplateFile = file("${jalviewDir}/${releases_template}")
1453 def whatsnewTemplateFile = file("${jalviewDir}/${whatsnew_template}")
1454 def releasesHtmlFile = file("${helpBuildDir}/${help_dir}/${releases_html}")
1455 def whatsnewHtmlFile = file("${helpBuildDir}/${help_dir}/${whatsnew_html}")
1456 def releasesMdDir = "${jalviewDir}/${releases_dir}"
1457 def whatsnewMdDir = "${jalviewDir}/${whatsnew_dir}"
1460 def releaseMdFile = file("${releasesMdDir}/release-${JALVIEW_VERSION_UNDERSCORES}.md")
1461 def whatsnewMdFile = file("${whatsnewMdDir}/whatsnew-${JALVIEW_VERSION_UNDERSCORES}.md")
1463 if (CHANNEL == "RELEASE") {
1464 if (!releaseMdFile.exists()) {
1465 throw new GradleException("File ${releaseMdFile} must be created for RELEASE")
1467 if (!whatsnewMdFile.exists()) {
1468 throw new GradleException("File ${whatsnewMdFile} must be created for RELEASE")
1472 def releaseFiles = fileTree(dir: releasesMdDir, include: "release-*.md")
1473 def releaseFilesDates = releaseFiles.collectEntries {
1474 [(it): getMdDate(it)]
1476 releaseFiles = releaseFiles.sort { a,b -> releaseFilesDates[a].compareTo(releaseFilesDates[b]) }
1478 def releasesTemplate = releasesTemplateFile.text
1479 def m = releasesTemplate =~ /(?s)__VERSION_LOOP_START__(.*)__VERSION_LOOP_END__/
1480 def versionTemplate = m[0][1]
1482 MutableDataSet options = new MutableDataSet()
1484 def extensions = new ArrayList<>()
1485 options.set(Parser.EXTENSIONS, extensions)
1486 options.set(Parser.HTML_BLOCK_COMMENT_ONLY_FULL_LINE, true)
1488 Parser parser = Parser.builder(options).build()
1489 HtmlRenderer renderer = HtmlRenderer.builder(options).build()
1491 def actualVersions = releaseFiles.collect { rf ->
1492 def (rfMap, rfContent) = mdFileComponents(rf)
1493 return rfMap.version
1495 def versionsHtml = ""
1496 def linkedVersions = []
1497 releaseFiles.reverse().each { rFile ->
1498 def (rMap, rContent) = mdFileComponents(rFile)
1500 def versionLink = ""
1501 def partialVersion = ""
1502 def firstPart = true
1503 rMap.version.split("\\.").each { part ->
1504 def displayPart = ( firstPart ? "" : "." ) + part
1505 partialVersion += displayPart
1507 linkedVersions.contains(partialVersion)
1508 || ( actualVersions.contains(partialVersion) && partialVersion != rMap.version )
1510 versionLink += displayPart
1512 versionLink += "<a id=\"Jalview.${partialVersion}\">${displayPart}</a>"
1513 linkedVersions += partialVersion
1517 def displayDate = releaseFilesDates[rFile].format("dd/MM/yyyy")
1520 def rContentProcessed = ""
1521 rContent.eachLine { line ->
1522 if (lm = line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
1523 line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}"
1524 } else if (lm = line =~ /^###([^#]+.*)$/) {
1525 line = "_${lm[0][1].trim()}_"
1527 rContentProcessed += line + "\n"
1530 def rContentSections = getMdSections(rContentProcessed)
1531 def rVersion = versionTemplate
1532 if (rVersion != "") {
1533 def rNewFeatures = rContentSections["new_features"]
1534 def rIssuesResolved = rContentSections["issues_resolved"]
1535 Node newFeaturesNode = parser.parse(rNewFeatures)
1536 String newFeaturesHtml = renderer.render(newFeaturesNode)
1537 Node issuesResolvedNode = parser.parse(rIssuesResolved)
1538 String issuesResolvedHtml = renderer.render(issuesResolvedNode)
1539 rVersion = hugoTemplateSubstitutions(rVersion,
1541 VERSION: rMap.version,
1542 VERSION_LINK: versionLink,
1543 DISPLAY_DATE: displayDate,
1544 NEW_FEATURES: newFeaturesHtml,
1545 ISSUES_RESOLVED: issuesResolvedHtml
1548 versionsHtml += rVersion
1552 releasesTemplate = releasesTemplate.replaceAll("(?s)__VERSION_LOOP_START__.*__VERSION_LOOP_END__", versionsHtml)
1553 releasesTemplate = hugoTemplateSubstitutions(releasesTemplate)
1554 releasesHtmlFile.text = releasesTemplate
1556 if (whatsnewMdFile.exists()) {
1557 def wnDisplayDate = releaseFilesDates[releaseMdFile] != null ? releaseFilesDates[releaseMdFile].format("dd MMMM yyyy") : ""
1558 def whatsnewMd = hugoTemplateSubstitutions(whatsnewMdFile.text)
1559 Node whatsnewNode = parser.parse(whatsnewMd)
1560 String whatsnewHtml = renderer.render(whatsnewNode)
1561 whatsnewHtml = whatsnewTemplateFile.text.replaceAll("__WHATS_NEW__", whatsnewHtml)
1562 whatsnewHtmlFile.text = hugoTemplateSubstitutions(whatsnewHtml,
1564 VERSION: JALVIEW_VERSION,
1565 DISPLAY_DATE: wnDisplayDate
1568 } else if (gradle.taskGraph.hasTask(":linkCheck")) {
1569 whatsnewHtmlFile.text = "Development build " + getDate("yyyy-MM-dd HH:mm:ss")
1574 inputs.file(releasesTemplateFile)
1575 inputs.file(whatsnewTemplateFile)
1576 inputs.dir(releasesMdDir)
1577 inputs.dir(whatsnewMdDir)
1578 outputs.file(releasesHtmlFile)
1579 outputs.file(whatsnewHtmlFile)
1583 task copyResources(type: Copy) {
1585 description = "Copy (and make text substitutions in) the resources dir to the build area"
1587 def inputDir = resourceDir
1588 def outputDir = resourcesBuildDir
1592 include('**/*.html')
1594 filter(ReplaceTokens,
1598 'Version-Rel': JALVIEW_VERSION,
1599 'Year-Rel': getDate("yyyy")
1606 exclude('**/*.html')
1611 inputs.dir(inputDir)
1612 outputs.dir(outputDir)
1615 task copyChannelResources(type: Copy) {
1616 dependsOn copyResources
1618 description = "Copy the channel resources dir to the build resources area"
1620 def inputDir = "${channelDir}/${resource_dir}"
1621 def outputDir = resourcesBuildDir
1625 inputs.dir(inputDir)
1626 outputs.dir(outputDir)
1629 task createBuildProperties(type: WriteProperties) {
1630 dependsOn copyResources
1632 description = "Create the ${buildProperties} file"
1634 inputs.dir(sourceDir)
1635 inputs.dir(resourcesBuildDir)
1636 outputFile (buildProperties)
1637 // taking time specific comment out to allow better incremental builds
1638 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1639 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1640 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1641 property "VERSION", JALVIEW_VERSION
1642 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1643 if (getdownSetAppBaseProperty) {
1644 property "GETDOWNAPPBASE", getdownAppBase
1645 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1647 outputs.file(outputFile)
1651 task buildIndices(type: JavaExec) {
1653 classpath = sourceSets.main.compileClasspath
1654 main = "com.sun.java.help.search.Indexer"
1655 workingDir = "${helpBuildDir}/${help_dir}"
1658 inputs.dir("${workingDir}/${argDir}")
1660 outputs.dir("${classesDir}/doc")
1661 outputs.dir("${classesDir}/help")
1662 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1663 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1664 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1665 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1666 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1667 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1670 task buildResources {
1671 dependsOn copyResources
1672 dependsOn copyChannelResources
1673 dependsOn createBuildProperties
1677 dependsOn buildResources
1680 dependsOn releasesTemplates
1681 dependsOn convertMdFiles
1682 dependsOn buildIndices
1686 compileJava.dependsOn prepare
1687 run.dependsOn compileJava
1688 //run.dependsOn prepare
1691 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1696 dependsOn cloverClasses
1698 dependsOn compileJava //?
1702 includeGroups testng_groups
1703 excludeGroups testng_excluded_groups
1705 useDefaultListeners=true
1708 maxHeapSize = "1024m"
1710 workingDir = jalviewDir
1711 def testLaf = project.findProperty("test_laf")
1712 if (testLaf != null) {
1713 println("Setting Test LaF to '${testLaf}'")
1714 systemProperty "laf", testLaf
1716 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1717 if (testHiDPIScale != null) {
1718 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1719 systemProperty "sun.java2d.uiScale", testHiDPIScale
1721 sourceCompatibility = compile_source_compatibility
1722 targetCompatibility = compile_target_compatibility
1723 jvmArgs += additional_compiler_args
1727 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1733 task compileLinkCheck(type: JavaCompile) {
1735 classpath = files("${jalviewDir}/${utils_dir}")
1736 destinationDir = file("${jalviewDir}/${utils_dir}")
1737 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1739 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1740 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1741 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1742 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1746 task linkCheck(type: JavaExec) {
1748 dependsOn compileLinkCheck
1750 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1751 classpath = files("${jalviewDir}/${utils_dir}")
1752 main = "HelpLinksChecker"
1753 workingDir = "${helpBuildDir}"
1754 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1756 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1757 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1760 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1764 inputs.dir(helpBuildDir)
1765 outputs.file(helpLinksCheckerOutFile)
1769 // import the pubhtmlhelp target
1770 ant.properties.basedir = "${jalviewDir}"
1771 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1772 ant.importBuild "${utils_dir}/publishHelp.xml"
1775 task cleanPackageDir(type: Delete) {
1777 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1787 attributes "Main-Class": main_class,
1788 "Permissions": "all-permissions",
1789 "Application-Name": applicationName,
1790 "Codebase": application_codebase,
1791 "Implementation-Version": JALVIEW_VERSION
1794 def outputDir = "${jalviewDir}/${package_dir}"
1795 destinationDirectory = file(outputDir)
1796 archiveFileName = rootProject.name+".jar"
1797 duplicatesStrategy "EXCLUDE"
1804 exclude "**/*.jar.*"
1806 inputs.dir(sourceSets.main.java.outputDir)
1807 sourceSets.main.resources.srcDirs.each{ dir ->
1810 outputs.file("${outputDir}/${archiveFileName}")
1814 task copyJars(type: Copy) {
1815 from fileTree(dir: classesDir, include: "**/*.jar").files
1816 into "${jalviewDir}/${package_dir}"
1820 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1821 task syncJars(type: Sync) {
1823 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1824 into "${jalviewDir}/${package_dir}"
1826 include jar.archiveFileName.getOrNull()
1833 description = "Put all required libraries in dist"
1834 // order of "cleanPackageDir", "copyJars", "jar" important!
1835 jar.mustRunAfter cleanPackageDir
1836 syncJars.mustRunAfter cleanPackageDir
1837 dependsOn cleanPackageDir
1840 outputs.dir("${jalviewDir}/${package_dir}")
1845 dependsOn cleanPackageDir
1852 group = "distribution"
1853 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1857 from ("${jalviewDir}/${libDistDir}") {
1861 attributes "Implementation-Version": JALVIEW_VERSION,
1862 "Application-Name": applicationName
1865 duplicatesStrategy "INCLUDE"
1867 mainClassName = shadow_jar_main_class
1869 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1874 task getdownWebsite() {
1875 group = "distribution"
1876 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1881 def getdownWebsiteResourceFilenames = []
1882 def getdownResourceDir = getdownResourceDir
1883 def getdownResourceFilenames = []
1886 // clean the getdown website and files dir before creating getdown folders
1887 delete getdownAppBaseDir
1888 delete getdownFilesDir
1891 from buildProperties
1892 rename(file(buildProperties).getName(), getdown_build_properties)
1895 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1898 from channelPropsFile
1899 into getdownAppBaseDir
1901 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1903 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1904 def props = project.properties.sort { it.key }
1905 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1906 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1908 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1909 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1911 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1912 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1914 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1915 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1916 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1917 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1918 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1919 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1920 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1923 props.put("getdown_txt_title", jalview_name)
1924 props.put("getdown_txt_ui.name", applicationName)
1926 // start with appbase
1927 getdownTextLines += "appbase = ${getdownAppBase}"
1928 props.each{ prop, val ->
1929 if (prop.startsWith("getdown_txt_") && val != null) {
1930 if (prop.startsWith("getdown_txt_multi_")) {
1931 def key = prop.substring(18)
1932 val.split(",").each{ v ->
1933 def line = "${key} = ${v}"
1934 getdownTextLines += line
1937 // file values rationalised
1938 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1940 if (val.indexOf('/') == 0) {
1943 } else if (val.indexOf('/') > 0) {
1944 // relative path (relative to jalviewDir)
1945 r = file( "${jalviewDir}/${val}" )
1948 val = "${getdown_resource_dir}/" + r.getName()
1949 getdownWebsiteResourceFilenames += val
1950 getdownResourceFilenames += r.getPath()
1953 if (! prop.startsWith("getdown_txt_resource")) {
1954 def line = prop.substring(12) + " = ${val}"
1955 getdownTextLines += line
1961 getdownWebsiteResourceFilenames.each{ filename ->
1962 getdownTextLines += "resource = ${filename}"
1964 getdownResourceFilenames.each{ filename ->
1967 into getdownResourceDir
1971 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1972 getdownWrapperScripts.each{ script ->
1973 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1977 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
1979 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1984 fileTree(file(package_dir)).each{ f ->
1985 if (f.isDirectory()) {
1986 def files = fileTree(dir: f, include: ["*"]).getFiles()
1988 } else if (f.exists()) {
1992 def jalviewJar = jar.archiveFileName.getOrNull()
1993 // put jalview.jar first for CLASSPATH and .properties files reasons
1994 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1995 def name = f.getName()
1996 def line = "code = ${getdownAppDistDir}/${name}"
1997 getdownTextLines += line
2004 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
2006 if (JAVA_VERSION.equals("11")) {
2007 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
2008 j11libFiles.sort().each{f ->
2009 def name = f.getName()
2010 def line = "code = ${getdown_j11lib_dir}/${name}"
2011 getdownTextLines += line
2014 into getdownJ11libDir
2020 // 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.
2021 //getdownTextLines += "class = " + file(getdownLauncher).getName()
2022 getdownTextLines += "resource = ${getdown_launcher_new}"
2023 getdownTextLines += "class = ${main_class}"
2024 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
2025 if (getdownSetAppBaseProperty) {
2026 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
2027 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
2030 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
2031 getdownTxt.write(getdownTextLines.join("\n"))
2033 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
2034 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
2035 launchJvl.write("appbase=${getdownAppBase}")
2037 // files going into the getdown website dir: getdown-launcher.jar
2039 from getdownLauncher
2040 rename(file(getdownLauncher).getName(), getdown_launcher_new)
2041 into getdownAppBaseDir
2044 // files going into the getdown website dir: getdown-launcher(-local).jar
2046 from getdownLauncher
2047 if (file(getdownLauncher).getName() != getdown_launcher) {
2048 rename(file(getdownLauncher).getName(), getdown_launcher)
2050 into getdownAppBaseDir
2053 // files going into the getdown website dir: ./install dir and files
2054 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
2057 from getdownLauncher
2058 from "${getdownAppDir}/${getdown_build_properties}"
2059 if (file(getdownLauncher).getName() != getdown_launcher) {
2060 rename(file(getdownLauncher).getName(), getdown_launcher)
2062 into getdownInstallDir
2065 // and make a copy in the getdown files dir (these are not downloaded by getdown)
2067 from getdownInstallDir
2068 into getdownFilesInstallDir
2072 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2076 from getdownLauncher
2077 from "${getdownAppBaseDir}/${getdown_build_properties}"
2078 from "${getdownAppBaseDir}/${channel_props}"
2079 if (file(getdownLauncher).getName() != getdown_launcher) {
2080 rename(file(getdownLauncher).getName(), getdown_launcher)
2082 into getdownFilesDir
2085 // and ./resource (not all downloaded by getdown)
2087 from getdownResourceDir
2088 into "${getdownFilesDir}/${getdown_resource_dir}"
2093 inputs.dir("${jalviewDir}/${package_dir}")
2095 outputs.dir(getdownAppBaseDir)
2096 outputs.dir(getdownFilesDir)
2100 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
2101 task getdownDigestDir(type: JavaExec) {
2103 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
2105 def digestDirPropertyName = "DIGESTDIR"
2107 classpath = files(getdownLauncher)
2108 def digestDir = findProperty(digestDirPropertyName)
2109 if (digestDir == null) {
2110 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
2114 main = "com.threerings.getdown.tools.Digester"
2118 task getdownDigest(type: JavaExec) {
2119 group = "distribution"
2120 description = "Digest the getdown website folder"
2121 dependsOn getdownWebsite
2123 classpath = files(getdownLauncher)
2125 main = "com.threerings.getdown.tools.Digester"
2126 args getdownAppBaseDir
2127 inputs.dir(getdownAppBaseDir)
2128 outputs.file("${getdownAppBaseDir}/digest2.txt")
2133 group = "distribution"
2134 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
2135 dependsOn getdownDigest
2137 if (reportRsyncCommand) {
2138 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
2139 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
2140 println "LIKELY RSYNC COMMAND:"
2141 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
2142 if (RUNRSYNC == "true") {
2144 commandLine "mkdir", "-p", toDir
2147 commandLine "rsync", "-avh", "--delete", fromDir, toDir
2155 task getdownArchiveBuild() {
2156 group = "distribution"
2157 description = "Put files in the archive dir to go on the website"
2159 dependsOn getdownWebsite
2161 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
2162 def vDir = "${getdownArchiveDir}/${v}"
2163 getdownFullArchiveDir = "${vDir}/getdown"
2164 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
2166 def vAltDir = "alt_${v}"
2167 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
2170 // cleanup old "old" dir
2171 delete getdownArchiveDir
2173 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
2174 getdownArchiveTxt.getParentFile().mkdirs()
2175 def getdownArchiveTextLines = []
2176 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
2180 from "${getdownAppBaseDir}/${getdownAppDistDir}"
2181 into "${getdownFullArchiveDir}/${vAltDir}"
2184 getdownTextLines.each { line ->
2185 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
2186 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
2187 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
2188 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
2189 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
2190 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
2191 // remove the existing resource = resource/ or bin/ lines
2192 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
2193 getdownArchiveTextLines += line
2197 // the resource dir -- add these files as resource lines in getdown.txt
2199 from "${archiveImagesDir}"
2200 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
2202 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
2206 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
2208 def vLaunchJvl = file(getdownVersionLaunchJvl)
2209 vLaunchJvl.getParentFile().mkdirs()
2210 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
2211 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
2212 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
2213 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
2214 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
2215 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
2217 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2219 from getdownLauncher
2220 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
2221 from "${getdownAppBaseDir}/${getdown_launcher_new}"
2222 from "${getdownAppBaseDir}/${channel_props}"
2223 if (file(getdownLauncher).getName() != getdown_launcher) {
2224 rename(file(getdownLauncher).getName(), getdown_launcher)
2226 into getdownFullArchiveDir
2232 task getdownArchiveDigest(type: JavaExec) {
2233 group = "distribution"
2234 description = "Digest the getdown archive folder"
2236 dependsOn getdownArchiveBuild
2239 classpath = files(getdownLauncher)
2240 args getdownFullArchiveDir
2242 main = "com.threerings.getdown.tools.Digester"
2243 inputs.dir(getdownFullArchiveDir)
2244 outputs.file("${getdownFullArchiveDir}/digest2.txt")
2247 task getdownArchive() {
2248 group = "distribution"
2249 description = "Build the website archive dir with getdown digest"
2251 dependsOn getdownArchiveBuild
2252 dependsOn getdownArchiveDigest
2255 tasks.withType(JavaCompile) {
2256 options.encoding = 'UTF-8'
2262 delete getdownAppBaseDir
2263 delete getdownFilesDir
2264 delete getdownArchiveDir
2270 if (file(install4jHomeDir).exists()) {
2272 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
2273 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
2274 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
2275 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
2277 installDir(file(install4jHomeDir))
2279 mediaTypes = Arrays.asList(install4j_media_types.split(","))
2283 task copyInstall4jTemplate {
2284 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
2285 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
2286 inputs.file(install4jTemplateFile)
2287 inputs.file(install4jFileAssociationsFile)
2288 inputs.property("CHANNEL", { CHANNEL })
2289 outputs.file(install4jConfFile)
2292 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
2294 // turn off code signing if no OSX_KEYPASS
2295 if (OSX_KEYPASS == "") {
2296 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
2297 codeSigning.'@macEnabled' = "false"
2299 install4jConfigXml.'**'.windows.each { windows ->
2300 windows.'@runPostProcessor' = "false"
2304 // disable install screen for OSX dmg (for 2.11.2.0)
2305 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
2306 macosArchive.attributes().remove('executeSetupApp')
2307 macosArchive.attributes().remove('setupAppId')
2310 // turn off checksum creation for LOCAL channel
2311 def e = install4jConfigXml.application[0]
2312 e.'@createChecksums' = string(install4jCheckSums)
2314 // put file association actions where placeholder action is
2315 def install4jFileAssociationsText = install4jFileAssociationsFile.text
2316 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
2317 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
2318 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
2319 def parent = a.parent()
2321 fileAssociationActions.each { faa ->
2324 // don't need to continue in .any loop once replacements have been made
2329 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
2330 // NB we're deleting the /other/ one!
2331 // Also remove the examples subdir from non-release versions
2332 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
2333 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
2334 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
2335 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
2337 // remove the examples subdir from Full File Set
2338 def files = install4jConfigXml.files[0]
2339 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
2340 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
2341 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
2342 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
2343 dirEntry.parent().remove(dirEntry)
2345 install4jConfigXml.'**'.action.any { a ->
2346 if (a.'@customizedId' == customizedIdToDelete) {
2347 def parent = a.parent()
2353 // write install4j file
2354 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2361 delete install4jConfFile
2365 task cleanInstallersDataFiles {
2366 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2367 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2368 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2370 delete installersOutputTxt
2371 delete installersSha256
2372 delete hugoDataJsonFile
2376 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2377 group = "distribution"
2378 description = "Create the install4j installers"
2380 dependsOn copyInstall4jTemplate
2381 dependsOn cleanInstallersDataFiles
2383 projectFile = install4jConfFile
2385 // create an md5 for the input files to use as version for install4j conf file
2386 def digest = MessageDigest.getInstance("MD5")
2388 (file("${install4jDir}/${install4j_template}").text +
2389 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2390 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2391 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2392 if (filesMd5.length() >= 8) {
2393 filesMd5 = filesMd5.substring(0,8)
2395 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2398 'JALVIEW_NAME': jalview_name,
2399 'JALVIEW_APPLICATION_NAME': applicationName,
2400 'JALVIEW_DIR': "../..",
2401 'OSX_KEYSTORE': OSX_KEYSTORE,
2402 'OSX_APPLEID': OSX_APPLEID,
2403 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2404 'JSIGN_SH': JSIGN_SH,
2405 'JRE_DIR': getdown_app_dir_java,
2406 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2407 'JALVIEW_VERSION': JALVIEW_VERSION,
2408 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2409 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2410 'JAVA_VERSION': JAVA_VERSION,
2411 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2412 'VERSION': JALVIEW_VERSION,
2413 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2414 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2415 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2416 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2417 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2418 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2419 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2420 'BUNDLE_ID': install4jBundleId,
2421 'INTERNAL_ID': install4jInternalId,
2422 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2423 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2424 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2425 'WRAPPER_LINK': getdownWrapperLink,
2426 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2427 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2428 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2429 'INSTALLER_NAME': install4jInstallerName,
2430 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2431 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2432 'GETDOWN_FILES_DIR': getdown_files_dir,
2433 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2434 'GETDOWN_DIST_DIR': getdownAppDistDir,
2435 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2436 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2437 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2438 'BUILD_DIR': install4jBuildDir,
2439 'APPLICATION_CATEGORIES': install4j_application_categories,
2440 'APPLICATION_FOLDER': install4jApplicationFolder,
2441 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2442 'EXECUTABLE_NAME': install4jExecutableName,
2443 'EXTRA_SCHEME': install4jExtraScheme,
2444 'MAC_ICONS_FILE': install4jMacIconsFile,
2445 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2446 'PNG_ICON_FILE': install4jPngIconFile,
2447 'BACKGROUND': install4jBackground,
2451 //println("INSTALL4J VARIABLES:")
2452 //variables.each{k,v->println("${k}=${v}")}
2454 destination = "${jalviewDir}/${install4jBuildDir}"
2455 buildSelected = true
2457 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2459 disableSigning = true
2460 disableNotarization = true
2464 macKeystorePassword = OSX_KEYPASS
2467 if (OSX_ALTOOLPASS) {
2468 appleIdPassword = OSX_ALTOOLPASS
2469 disableNotarization = false
2471 disableNotarization = true
2475 println("Using projectFile "+projectFile)
2476 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2480 inputs.dir(getdownAppBaseDir)
2481 inputs.file(install4jConfFile)
2482 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2483 inputs.dir(macosJavaVMDir)
2484 inputs.dir(windowsJavaVMDir)
2485 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2488 def getDataHash(File myFile) {
2489 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2490 return myFile.exists()
2492 "file" : myFile.getName(),
2493 "filesize" : myFile.length(),
2494 "sha256" : hash.toString()
2499 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2501 "channel" : getdownChannelName,
2502 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2503 "git-commit" : "${gitHash} [${gitBranch}]",
2504 "version" : JALVIEW_VERSION
2506 // install4j installer files
2507 if (installersOutputTxt.exists()) {
2509 installersOutputTxt.readLines().each { def line ->
2510 if (line.startsWith("#")) {
2513 line.replaceAll("\n","")
2514 def vals = line.split("\t")
2515 def filename = vals[3]
2516 def filesize = file(filename).length()
2517 filename = filename.replaceAll(/^.*\//, "")
2518 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2519 idHash."${filename}" = vals[0]
2521 if (install4jCheckSums && installersSha256.exists()) {
2522 installersSha256.readLines().each { def line ->
2523 if (line.startsWith("#")) {
2526 line.replaceAll("\n","")
2527 def vals = line.split(/\s+\*?/)
2528 def filename = vals[1]
2529 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2535 "JAR": shadowJar.archiveFile, // executable JAR
2536 "JVL": getdownVersionLaunchJvl, // version JVL
2537 "SOURCE": sourceDist.archiveFile // source TGZ
2538 ].each { key, value ->
2539 def file = file(value)
2540 if (file.exists()) {
2541 def fileHash = getDataHash(file)
2542 if (fileHash != null) {
2543 hash."${key}" = fileHash;
2547 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2550 task staticMakeInstallersJsonFile {
2552 def output = findProperty("i4j_output")
2553 def sha256 = findProperty("i4j_sha256")
2554 def json = findProperty("i4j_json")
2555 if (output == null || sha256 == null || json == null) {
2556 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2558 writeDataJsonFile(file(output), file(sha256), file(json))
2563 dependsOn installerFiles
2569 eclipse().configFile(eclipse_codestyle_file)
2573 task createSourceReleaseProperties(type: WriteProperties) {
2574 group = "distribution"
2575 description = "Create the source RELEASE properties file"
2577 def sourceTarBuildDir = "${buildDir}/sourceTar"
2578 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2579 outputFile (sourceReleasePropertiesFile)
2582 releaseProps.each{ key, val -> property key, val }
2583 property "git.branch", gitBranch
2584 property "git.hash", gitHash
2587 outputs.file(outputFile)
2590 task sourceDist(type: Tar) {
2591 group "distribution"
2592 description "Create a source .tar.gz file for distribution"
2594 dependsOn createBuildProperties
2595 dependsOn convertMdFiles
2596 dependsOn eclipseAllPreferences
2597 dependsOn createSourceReleaseProperties
2600 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2601 archiveFileName = outputFileName
2603 compression Compression.GZIP
2618 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2620 "utils/InstallAnywhere",
2635 "gradle.properties",
2647 ".settings/org.eclipse.buildship.core.prefs",
2648 ".settings/org.eclipse.jdt.core.prefs"
2652 exclude (EXCLUDE_FILES)
2653 include (PROCESS_FILES)
2654 filter(ReplaceTokens,
2658 'Version-Rel': JALVIEW_VERSION,
2659 'Year-Rel': getDate("yyyy")
2664 exclude (EXCLUDE_FILES)
2665 exclude (PROCESS_FILES)
2666 exclude ("appletlib")
2667 exclude ("**/*locales")
2668 exclude ("*locales/**")
2669 exclude ("utils/InstallAnywhere")
2671 exclude (getdown_files_dir)
2672 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2673 //exclude (getdown_website_dir)
2674 //exclude (getdown_archive_dir)
2676 // exluding these as not using jars as modules yet
2677 exclude ("${j11modDir}/**/*.jar")
2680 include(INCLUDE_FILES)
2682 // from (jalviewDir) {
2683 // // explicit includes for stuff that seemed to not get included
2684 // include(fileTree("test/**/*."))
2685 // exclude(EXCLUDE_FILES)
2686 // exclude(PROCESS_FILES)
2689 from(file(buildProperties).getParent()) {
2690 include(file(buildProperties).getName())
2691 rename(file(buildProperties).getName(), "build_properties")
2693 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2697 def sourceTarBuildDir = "${buildDir}/sourceTar"
2698 from(sourceTarBuildDir) {
2699 // this includes the appended RELEASE properties file
2703 task dataInstallersJson {
2705 description "Create the installers-VERSION.json data file for installer files created"
2707 mustRunAfter installers
2708 mustRunAfter shadowJar
2709 mustRunAfter sourceDist
2710 mustRunAfter getdownArchive
2712 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2713 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2715 if (installersOutputTxt.exists()) {
2716 inputs.file(installersOutputTxt)
2718 if (install4jCheckSums && installersSha256.exists()) {
2719 inputs.file(installersSha256)
2722 shadowJar.archiveFile, // executable JAR
2723 getdownVersionLaunchJvl, // version JVL
2724 sourceDist.archiveFile // source TGZ
2725 ].each { fileName ->
2726 if (file(fileName).exists()) {
2727 inputs.file(fileName)
2731 outputs.file(hugoDataJsonFile)
2734 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2740 description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'."
2743 dependsOn pubhtmlhelp
2745 inputs.dir("${helpBuildDir}/${help_dir}")
2746 outputs.dir("${buildDir}/distributions/${help_dir}")
2750 task j2sSetHeadlessBuild {
2757 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2759 description "Enable the alternative J2S Config file for headless build"
2761 outputFile = jalviewjsJ2sSettingsFileName
2762 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2763 def j2sProps = new Properties()
2764 if (j2sPropsFile.exists()) {
2766 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2767 j2sProps.load(j2sPropsFileFIS)
2768 j2sPropsFileFIS.close()
2770 j2sProps.each { prop, val ->
2773 } catch (Exception e) {
2774 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2778 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2779 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2784 task jalviewjsSetEclipseWorkspace {
2785 def propKey = "jalviewjs_eclipse_workspace"
2787 if (project.hasProperty(propKey)) {
2788 propVal = project.getProperty(propKey)
2789 if (propVal.startsWith("~/")) {
2790 propVal = System.getProperty("user.home") + propVal.substring(1)
2793 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2794 def propsFile = file(propsFileName)
2795 def eclipseWsDir = propVal
2796 def props = new Properties()
2798 def writeProps = true
2799 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2800 def ins = new FileInputStream(propsFileName)
2803 if (props.getProperty(propKey, null) != null) {
2804 eclipseWsDir = props.getProperty(propKey)
2809 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2810 def tempDir = File.createTempDir()
2811 eclipseWsDir = tempDir.getAbsolutePath()
2814 eclipseWorkspace = file(eclipseWsDir)
2817 // do not run a headless transpile when we claim to be in Eclipse
2819 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2820 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2822 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2826 props.setProperty(propKey, eclipseWsDir)
2827 propsFile.parentFile.mkdirs()
2828 def bytes = new ByteArrayOutputStream()
2829 props.store(bytes, null)
2830 def propertiesString = bytes.toString()
2831 propsFile.text = propertiesString
2837 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2840 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2841 outputs.file(propsFileName)
2842 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2846 task jalviewjsEclipsePaths {
2849 def eclipseRoot = jalviewjs_eclipse_root
2850 if (eclipseRoot.startsWith("~/")) {
2851 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2853 if (OperatingSystem.current().isMacOsX()) {
2854 eclipseRoot += "/Eclipse.app"
2855 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2856 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2857 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2858 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2859 eclipseRoot += "/eclipse"
2861 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2862 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2863 } else { // linux or unix
2864 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2865 eclipseRoot += "/eclipse"
2866 println("eclipseDir exists")
2868 eclipseBinary = "${eclipseRoot}/eclipse"
2869 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2872 eclipseVersion = "4.13" // default
2873 def assumedVersion = true
2874 if (file(eclipseProduct).exists()) {
2875 def fis = new FileInputStream(eclipseProduct)
2876 def props = new Properties()
2878 eclipseVersion = props.getProperty("version")
2880 assumedVersion = false
2883 def propKey = "eclipse_debug"
2884 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2887 // do not run a headless transpile when we claim to be in Eclipse
2889 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2890 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2892 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2895 if (!assumedVersion) {
2896 println("ECLIPSE VERSION=${eclipseVersion}")
2902 task printProperties {
2904 description "Output to console all System.properties"
2906 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2912 dependsOn eclipseProject
2913 dependsOn eclipseClasspath
2914 dependsOn eclipseJdt
2918 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2919 task jalviewjsEclipseCopyDropins(type: Copy) {
2920 dependsOn jalviewjsEclipsePaths
2922 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2923 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2924 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2931 // this eclipse -clean doesn't actually work
2932 task jalviewjsCleanEclipse(type: Exec) {
2933 dependsOn eclipseSetup
2934 dependsOn jalviewjsEclipsePaths
2935 dependsOn jalviewjsEclipseCopyDropins
2937 executable(eclipseBinary)
2938 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2944 def inputString = """exit
2947 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2948 standardInput = inputByteStream
2951 /* not really working yet
2952 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2956 task jalviewjsTransferUnzipSwingJs {
2957 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2961 from zipTree(file_zip)
2962 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2966 inputs.file file_zip
2967 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2971 task jalviewjsTransferUnzipLib {
2972 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2975 zipFiles.each { file_zip ->
2977 from zipTree(file_zip)
2978 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2983 inputs.files zipFiles
2984 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2988 task jalviewjsTransferUnzipAllLibs {
2989 dependsOn jalviewjsTransferUnzipSwingJs
2990 dependsOn jalviewjsTransferUnzipLib
2994 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2996 description "Create the alternative j2s file from the j2s.* properties"
2998 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2999 def siteDirProperty = "j2s.site.directory"
3000 def setSiteDir = false
3001 jalviewjsJ2sProps.each { prop, val ->
3003 if (prop == siteDirProperty) {
3004 if (!(val.startsWith('/') || val.startsWith("file://") )) {
3005 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3011 if (!setSiteDir) { // default site location, don't override specifically set property
3012 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3015 outputFile = jalviewjsJ2sAltSettingsFileName
3018 inputs.properties(jalviewjsJ2sProps)
3019 outputs.file(jalviewjsJ2sAltSettingsFileName)
3024 task jalviewjsEclipseSetup {
3025 dependsOn jalviewjsEclipseCopyDropins
3026 dependsOn jalviewjsSetEclipseWorkspace
3027 dependsOn jalviewjsCreateJ2sSettings
3031 task jalviewjsSyncAllLibs (type: Sync) {
3032 dependsOn jalviewjsTransferUnzipAllLibs
3033 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3034 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3035 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3039 def outputFiles = []
3040 rename { filename ->
3041 outputFiles += "${outputDir}/${filename}"
3048 // should this be exclude really ?
3049 duplicatesStrategy "INCLUDE"
3051 outputs.files outputFiles
3052 inputs.files inputFiles
3056 task jalviewjsSyncResources (type: Sync) {
3057 dependsOn buildResources
3059 def inputFiles = fileTree(dir: resourcesBuildDir)
3060 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3064 def outputFiles = []
3065 rename { filename ->
3066 outputFiles += "${outputDir}/${filename}"
3072 outputs.files outputFiles
3073 inputs.files inputFiles
3077 task jalviewjsSyncSiteResources (type: Sync) {
3078 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3079 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3083 def outputFiles = []
3084 rename { filename ->
3085 outputFiles += "${outputDir}/${filename}"
3091 outputs.files outputFiles
3092 inputs.files inputFiles
3096 task jalviewjsSyncBuildProperties (type: Sync) {
3097 dependsOn createBuildProperties
3098 def inputFiles = [file(buildProperties)]
3099 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3103 def outputFiles = []
3104 rename { filename ->
3105 outputFiles += "${outputDir}/${filename}"
3111 outputs.files outputFiles
3112 inputs.files inputFiles
3116 task jalviewjsProjectImport(type: Exec) {
3117 dependsOn eclipseSetup
3118 dependsOn jalviewjsEclipsePaths
3119 dependsOn jalviewjsEclipseSetup
3122 // do not run a headless import when we claim to be in Eclipse
3124 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3125 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3127 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3131 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3132 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3133 executable(eclipseBinary)
3134 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3138 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3140 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3141 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3144 inputs.file("${jalviewDir}/.project")
3145 outputs.upToDateWhen {
3146 file(projdir).exists()
3151 task jalviewjsTranspile(type: Exec) {
3152 dependsOn jalviewjsEclipseSetup
3153 dependsOn jalviewjsProjectImport
3154 dependsOn jalviewjsEclipsePaths
3156 dependsOn jalviewjsEnableAltFileProperty
3160 // do not run a headless transpile when we claim to be in Eclipse
3162 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3163 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3165 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3169 executable(eclipseBinary)
3170 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3174 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3176 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3177 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3183 stdout = new ByteArrayOutputStream()
3184 stderr = new ByteArrayOutputStream()
3186 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3187 def logOutFile = file(logOutFileName)
3188 logOutFile.createNewFile()
3189 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3190 BINARY: ${eclipseBinary}
3191 VERSION: ${eclipseVersion}
3192 WORKSPACE: ${eclipseWorkspace}
3193 DEBUG: ${eclipseDebug}
3196 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3197 // combine stdout and stderr
3198 def logErrFOS = logOutFOS
3200 if (jalviewjs_j2s_to_console.equals("true")) {
3201 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3202 new org.apache.tools.ant.util.TeeOutputStream(
3206 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3207 new org.apache.tools.ant.util.TeeOutputStream(
3212 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3215 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3222 if (stdout.toString().contains("Error processing ")) {
3223 // j2s did not complete transpile
3224 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3225 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3226 println("IGNORING TRANSPILE ERRORS")
3227 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3229 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3234 inputs.dir("${jalviewDir}/${sourceDir}")
3235 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3236 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3240 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3242 def stdout = new ByteArrayOutputStream()
3243 def stderr = new ByteArrayOutputStream()
3245 def coreFile = file(jsfile)
3247 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3249 logOutFile.createNewFile()
3250 logOutFile.append(msg+"\n")
3252 def coreTop = file(prefixFile)
3253 def coreBottom = file(suffixFile)
3254 coreFile.getParentFile().mkdirs()
3255 coreFile.createNewFile()
3256 coreFile.write( coreTop.getText("UTF-8") )
3260 def t = f.getText("UTF-8")
3261 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3262 coreFile.append( t )
3264 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3266 logOutFile.append(msg+"\n")
3269 coreFile.append( coreBottom.getText("UTF-8") )
3271 msg = "Generating ${zjsfile}"
3273 logOutFile.append(msg+"\n")
3274 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3275 def logErrFOS = logOutFOS
3278 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3279 main = "com.google.javascript.jscomp.CommandLineRunner"
3280 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3281 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3284 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3286 logOutFile.append(msg+"\n")
3288 if (logOutConsole) {
3289 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3290 new org.apache.tools.ant.util.TeeOutputStream(
3294 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3295 new org.apache.tools.ant.util.TeeOutputStream(
3300 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3303 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3310 logOutFile.append(msg+"\n")
3314 task jalviewjsBuildAllCores {
3316 description "Build the core js lib closures listed in the classlists dir"
3317 dependsOn jalviewjsTranspile
3318 dependsOn jalviewjsTransferUnzipSwingJs
3320 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3321 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3322 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3323 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3324 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3325 def prefixFile = "${jsDir}/core/coretop2.js"
3326 def suffixFile = "${jsDir}/core/corebottom2.js"
3328 inputs.file prefixFile
3329 inputs.file suffixFile
3331 def classlistFiles = []
3332 // add the classlists found int the jalviewjs_classlists_dir
3333 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3335 def name = file.getName() - ".txt"
3342 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3343 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3344 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3346 jalviewjsCoreClasslists = []
3348 classlistFiles.each {
3351 def file = hash['file']
3352 if (! file.exists()) {
3353 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3354 return false // this is a "continue" in groovy .each closure
3356 def name = hash['name']
3358 name = file.getName() - ".txt"
3366 def list = fileTree(dir: j2sDir, includes: filelist)
3368 def jsfile = "${outputDir}/core${name}.js"
3369 def zjsfile = "${outputDir}/core${name}.z.js"
3371 jalviewjsCoreClasslists += [
3380 outputs.file(jsfile)
3381 outputs.file(zjsfile)
3384 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3385 def stevesoftClasslistName = "_stevesoft"
3386 def stevesoftClasslist = [
3387 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3388 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3389 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3390 'name': stevesoftClasslistName
3392 jalviewjsCoreClasslists += stevesoftClasslist
3393 inputs.files(stevesoftClasslist['list'])
3394 outputs.file(stevesoftClasslist['jsfile'])
3395 outputs.file(stevesoftClasslist['zjsfile'])
3398 def allClasslistName = "_all"
3399 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3400 allJsFiles += fileTree(
3404 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3405 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3406 "**/org/jmol/export/JSExporter.js"
3409 allJsFiles += fileTree(
3413 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3414 "**/sun/misc/Unsafe.js",
3415 "**/swingjs/jquery/jquery-editable-select.js",
3416 "**/swingjs/jquery/j2sComboBox.js",
3417 "**/sun/misc/FloatingDecimal.js"
3420 def allClasslist = [
3421 'jsfile': "${outputDir}/core${allClasslistName}.js",
3422 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3424 'name': allClasslistName
3426 // not including this version of "all" core at the moment
3427 //jalviewjsCoreClasslists += allClasslist
3428 inputs.files(allClasslist['list'])
3429 outputs.file(allClasslist['jsfile'])
3430 outputs.file(allClasslist['zjsfile'])
3433 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3434 logOutFile.getParentFile().mkdirs()
3435 logOutFile.createNewFile()
3436 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3438 jalviewjsCoreClasslists.each {
3439 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3446 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3449 into file(outputFile).getParentFile()
3450 rename { filename ->
3451 if (filename.equals(inputFile.getName())) {
3452 return file(outputFile).getName()
3456 filter(ReplaceTokens,
3460 'MAIN': '"'+main_class+'"',
3462 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3463 'COREKEY': jalviewjs_core_key,
3464 'CORENAME': coreName
3471 task jalviewjsPublishCoreTemplates {
3472 dependsOn jalviewjsBuildAllCores
3473 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3474 def inputFile = file(inputFileName)
3475 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3477 def outputFiles = []
3478 jalviewjsCoreClasslists.each { cl ->
3479 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3480 cl['outputfile'] = outputFile
3481 outputFiles += outputFile
3485 jalviewjsCoreClasslists.each { cl ->
3486 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3489 inputs.file(inputFile)
3490 outputs.files(outputFiles)
3494 task jalviewjsSyncCore (type: Sync) {
3495 dependsOn jalviewjsBuildAllCores
3496 dependsOn jalviewjsPublishCoreTemplates
3497 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3498 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3502 def outputFiles = []
3503 rename { filename ->
3504 outputFiles += "${outputDir}/${filename}"
3510 outputs.files outputFiles
3511 inputs.files inputFiles
3515 // this Copy version of TransferSiteJs will delete anything else in the target dir
3516 task jalviewjsCopyTransferSiteJs(type: Copy) {
3517 dependsOn jalviewjsTranspile
3518 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3519 into "${jalviewDir}/${jalviewjsSiteDir}"
3523 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3524 task jalviewjsSyncTransferSiteJs(type: Sync) {
3525 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3527 into "${jalviewDir}/${jalviewjsSiteDir}"
3534 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3535 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3536 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3537 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3539 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3540 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3541 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3542 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3545 task jalviewjsPrepareSite {
3547 description "Prepares the website folder including unzipping files and copying resources"
3548 dependsOn jalviewjsSyncAllLibs
3549 dependsOn jalviewjsSyncResources
3550 dependsOn jalviewjsSyncSiteResources
3551 dependsOn jalviewjsSyncBuildProperties
3552 dependsOn jalviewjsSyncCore
3556 task jalviewjsBuildSite {
3558 description "Builds the whole website including transpiled code"
3559 dependsOn jalviewjsCopyTransferSiteJs
3560 dependsOn jalviewjsPrepareSite
3564 task cleanJalviewjsTransferSite {
3566 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3567 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3568 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3569 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3574 task cleanJalviewjsSite {
3575 dependsOn cleanJalviewjsTransferSite
3577 delete "${jalviewDir}/${jalviewjsSiteDir}"
3582 task jalviewjsSiteTar(type: Tar) {
3584 description "Creates a tar.gz file for the website"
3585 dependsOn jalviewjsBuildSite
3586 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3587 archiveFileName = outputFilename
3589 compression Compression.GZIP
3591 from "${jalviewDir}/${jalviewjsSiteDir}"
3592 into jalviewjs_site_dir // this is inside the tar file
3594 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3598 task jalviewjsServer {
3600 def filename = "jalviewjsTest.html"
3601 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3602 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3607 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3608 factory = f.newInstance()
3609 } catch (ClassNotFoundException e) {
3610 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3612 def port = Integer.valueOf(jalviewjs_server_port)
3617 while(port < start+1000 && !running) {
3619 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3620 jalviewjsServer = factory.start(doc_root, port)
3622 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3623 println("SERVER STARTED with document root ${doc_root}.")
3624 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3625 println("For debug: "+url+"?j2sdebug")
3626 println("For verbose: "+url+"?j2sverbose")
3627 } catch (Exception e) {
3632 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3633 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3634 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3636 jalviewjsCoreClasslists.each { cl ->
3637 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3639 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3641 println("For core ${cl.name}: "+urlcore)
3644 file(htmlFile).text = htmlText
3647 outputs.file(htmlFile)
3648 outputs.upToDateWhen({false})
3652 task cleanJalviewjsAll {
3654 description "Delete all configuration and build artifacts to do with JalviewJS build"
3655 dependsOn cleanJalviewjsSite
3656 dependsOn jalviewjsEclipsePaths
3659 delete "${jalviewDir}/${jalviewjsBuildDir}"
3660 delete "${jalviewDir}/${eclipse_bin_dir}"
3661 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3662 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3664 delete jalviewjsJ2sAltSettingsFileName
3667 outputs.upToDateWhen( { false } )
3671 task jalviewjsIDE_checkJ2sPlugin {
3672 group "00 JalviewJS in Eclipse"
3673 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3676 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3677 def j2sPluginFile = file(j2sPlugin)
3678 def eclipseHome = System.properties["eclipse.home.location"]
3679 if (eclipseHome == null || ! IN_ECLIPSE) {
3680 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3682 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3683 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3684 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3685 eclipseJ2sPluginDirs += altPluginsDir
3687 def foundPlugin = false
3688 def j2sPluginFileName = j2sPluginFile.getName()
3689 def eclipseJ2sPlugin
3690 def eclipseJ2sPluginFile
3691 eclipseJ2sPluginDirs.any { dir ->
3692 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3693 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3694 if (eclipseJ2sPluginFile.exists()) {
3700 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3701 System.err.println(msg)
3702 throw new StopExecutionException(msg)
3705 def digest = MessageDigest.getInstance("MD5")
3707 digest.update(j2sPluginFile.text.bytes)
3708 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3710 digest.update(eclipseJ2sPluginFile.text.bytes)
3711 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3713 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3714 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3715 System.err.println(msg)
3716 throw new StopExecutionException(msg)
3718 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3724 task jalviewjsIDE_copyJ2sPlugin {
3725 group "00 JalviewJS in Eclipse"
3726 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3729 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3730 def j2sPluginFile = file(j2sPlugin)
3731 def eclipseHome = System.properties["eclipse.home.location"]
3732 if (eclipseHome == null || ! IN_ECLIPSE) {
3733 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3735 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3736 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3737 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3738 System.err.println(msg)
3741 eclipseJ2sPluginFile.getParentFile().mkdirs()
3742 into eclipseJ2sPluginFile.getParent()
3748 task jalviewjsIDE_j2sFile {
3749 group "00 JalviewJS in Eclipse"
3750 description "Creates the .j2s file"
3751 dependsOn jalviewjsCreateJ2sSettings
3755 task jalviewjsIDE_SyncCore {
3756 group "00 JalviewJS in Eclipse"
3757 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3758 dependsOn jalviewjsSyncCore
3762 task jalviewjsIDE_SyncSiteAll {
3763 dependsOn jalviewjsSyncAllLibs
3764 dependsOn jalviewjsSyncResources
3765 dependsOn jalviewjsSyncSiteResources
3766 dependsOn jalviewjsSyncBuildProperties
3770 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3773 task jalviewjsIDE_PrepareSite {
3774 group "00 JalviewJS in Eclipse"
3775 description "Sync libs and resources to site dir, but not closure cores"
3777 dependsOn jalviewjsIDE_SyncSiteAll
3778 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3782 task jalviewjsIDE_AssembleSite {
3783 group "00 JalviewJS in Eclipse"
3784 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3785 dependsOn jalviewjsPrepareSite
3789 task jalviewjsIDE_SiteClean {
3790 group "00 JalviewJS in Eclipse"
3791 description "Deletes the Eclipse transpiled site"
3792 dependsOn cleanJalviewjsSite
3796 task jalviewjsIDE_Server {
3797 group "00 JalviewJS in Eclipse"
3798 description "Starts a webserver on localhost to test the website"
3799 dependsOn jalviewjsServer
3803 // buildship runs this at import or gradle refresh
3804 task eclipseSynchronizationTask {
3805 //dependsOn eclipseSetup
3806 dependsOn createBuildProperties
3808 dependsOn jalviewjsIDE_j2sFile
3809 dependsOn jalviewjsIDE_checkJ2sPlugin
3810 dependsOn jalviewjsIDE_PrepareSite
3815 // buildship runs this at build time or project refresh
3816 task eclipseAutoBuildTask {
3817 //dependsOn jalviewjsIDE_checkJ2sPlugin
3818 //dependsOn jalviewjsIDE_PrepareSite
3824 description "Build the site"
3825 dependsOn jalviewjsBuildSite