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 DISPLAY_DATE: wnDisplayDate
1567 } else if (gradle.taskGraph.hasTask(":linkCheck")) {
1568 whatsnewHtmlFile.text = "Development build " + getDate("yyyy-MM-dd HH:mm:ss")
1573 inputs.file(releasesTemplateFile)
1574 inputs.file(whatsnewTemplateFile)
1575 inputs.dir(releasesMdDir)
1576 inputs.dir(whatsnewMdDir)
1577 outputs.file(releasesHtmlFile)
1578 outputs.file(whatsnewHtmlFile)
1582 task copyResources(type: Copy) {
1584 description = "Copy (and make text substitutions in) the resources dir to the build area"
1586 def inputDir = resourceDir
1587 def outputDir = resourcesBuildDir
1591 include('**/*.html')
1593 filter(ReplaceTokens,
1597 'Version-Rel': JALVIEW_VERSION,
1598 'Year-Rel': getDate("yyyy")
1605 exclude('**/*.html')
1610 inputs.dir(inputDir)
1611 outputs.dir(outputDir)
1614 task copyChannelResources(type: Copy) {
1615 dependsOn copyResources
1617 description = "Copy the channel resources dir to the build resources area"
1619 def inputDir = "${channelDir}/${resource_dir}"
1620 def outputDir = resourcesBuildDir
1624 inputs.dir(inputDir)
1625 outputs.dir(outputDir)
1628 task createBuildProperties(type: WriteProperties) {
1629 dependsOn copyResources
1631 description = "Create the ${buildProperties} file"
1633 inputs.dir(sourceDir)
1634 inputs.dir(resourcesBuildDir)
1635 outputFile (buildProperties)
1636 // taking time specific comment out to allow better incremental builds
1637 comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd HH:mm:ss")
1638 //comment "--Jalview Build Details--\n"+getDate("yyyy-MM-dd")
1639 property "BUILD_DATE", getDate("HH:mm:ss dd MMMM yyyy")
1640 property "VERSION", JALVIEW_VERSION
1641 property "INSTALLATION", INSTALLATION+" git-commit:"+gitHash+" ["+gitBranch+"]"
1642 if (getdownSetAppBaseProperty) {
1643 property "GETDOWNAPPBASE", getdownAppBase
1644 property "GETDOWNAPPDISTDIR", getdownAppDistDir
1646 outputs.file(outputFile)
1650 task buildIndices(type: JavaExec) {
1652 classpath = sourceSets.main.compileClasspath
1653 main = "com.sun.java.help.search.Indexer"
1654 workingDir = "${helpBuildDir}/${help_dir}"
1657 inputs.dir("${workingDir}/${argDir}")
1659 outputs.dir("${classesDir}/doc")
1660 outputs.dir("${classesDir}/help")
1661 outputs.file("${workingDir}/JavaHelpSearch/DOCS")
1662 outputs.file("${workingDir}/JavaHelpSearch/DOCS.TAB")
1663 outputs.file("${workingDir}/JavaHelpSearch/OFFSETS")
1664 outputs.file("${workingDir}/JavaHelpSearch/POSITIONS")
1665 outputs.file("${workingDir}/JavaHelpSearch/SCHEMA")
1666 outputs.file("${workingDir}/JavaHelpSearch/TMAP")
1669 task buildResources {
1670 dependsOn copyResources
1671 dependsOn copyChannelResources
1672 dependsOn createBuildProperties
1676 dependsOn buildResources
1679 dependsOn releasesTemplates
1680 dependsOn convertMdFiles
1681 dependsOn buildIndices
1685 compileJava.dependsOn prepare
1686 run.dependsOn compileJava
1687 //run.dependsOn prepare
1690 //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
1695 dependsOn cloverClasses
1697 dependsOn compileJava //?
1701 includeGroups testng_groups
1702 excludeGroups testng_excluded_groups
1704 useDefaultListeners=true
1707 maxHeapSize = "1024m"
1709 workingDir = jalviewDir
1710 def testLaf = project.findProperty("test_laf")
1711 if (testLaf != null) {
1712 println("Setting Test LaF to '${testLaf}'")
1713 systemProperty "laf", testLaf
1715 def testHiDPIScale = project.findProperty("test_HiDPIScale")
1716 if (testHiDPIScale != null) {
1717 println("Setting Test HiDPI Scale to '${testHiDPIScale}'")
1718 systemProperty "sun.java2d.uiScale", testHiDPIScale
1720 sourceCompatibility = compile_source_compatibility
1721 targetCompatibility = compile_target_compatibility
1722 jvmArgs += additional_compiler_args
1726 println("Running tests " + (useClover?"WITH":"WITHOUT") + " clover")
1732 task compileLinkCheck(type: JavaCompile) {
1734 classpath = files("${jalviewDir}/${utils_dir}")
1735 destinationDir = file("${jalviewDir}/${utils_dir}")
1736 source = fileTree(dir: "${jalviewDir}/${utils_dir}", include: ["HelpLinksChecker.java", "BufferedLineReader.java"])
1738 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1739 inputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.java")
1740 outputs.file("${jalviewDir}/${utils_dir}/HelpLinksChecker.class")
1741 outputs.file("${jalviewDir}/${utils_dir}/BufferedLineReader.class")
1745 task linkCheck(type: JavaExec) {
1747 dependsOn compileLinkCheck
1749 def helpLinksCheckerOutFile = file("${jalviewDir}/${utils_dir}/HelpLinksChecker.out")
1750 classpath = files("${jalviewDir}/${utils_dir}")
1751 main = "HelpLinksChecker"
1752 workingDir = "${helpBuildDir}"
1753 args = [ "${helpBuildDir}/${help_dir}", "-nointernet" ]
1755 def outFOS = new FileOutputStream(helpLinksCheckerOutFile, false) // false == don't append
1756 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
1759 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
1763 inputs.dir(helpBuildDir)
1764 outputs.file(helpLinksCheckerOutFile)
1768 // import the pubhtmlhelp target
1769 ant.properties.basedir = "${jalviewDir}"
1770 ant.properties.helpBuildDir = "${helpBuildDir}/${help_dir}"
1771 ant.importBuild "${utils_dir}/publishHelp.xml"
1774 task cleanPackageDir(type: Delete) {
1776 delete fileTree(dir: "${jalviewDir}/${package_dir}", include: "*.jar")
1786 attributes "Main-Class": main_class,
1787 "Permissions": "all-permissions",
1788 "Application-Name": applicationName,
1789 "Codebase": application_codebase,
1790 "Implementation-Version": JALVIEW_VERSION
1793 def outputDir = "${jalviewDir}/${package_dir}"
1794 destinationDirectory = file(outputDir)
1795 archiveFileName = rootProject.name+".jar"
1796 duplicatesStrategy "EXCLUDE"
1803 exclude "**/*.jar.*"
1805 inputs.dir(sourceSets.main.java.outputDir)
1806 sourceSets.main.resources.srcDirs.each{ dir ->
1809 outputs.file("${outputDir}/${archiveFileName}")
1813 task copyJars(type: Copy) {
1814 from fileTree(dir: classesDir, include: "**/*.jar").files
1815 into "${jalviewDir}/${package_dir}"
1819 // doing a Sync instead of Copy as Copy doesn't deal with "outputs" very well
1820 task syncJars(type: Sync) {
1822 from fileTree(dir: "${jalviewDir}/${libDistDir}", include: "**/*.jar").files
1823 into "${jalviewDir}/${package_dir}"
1825 include jar.archiveFileName.getOrNull()
1832 description = "Put all required libraries in dist"
1833 // order of "cleanPackageDir", "copyJars", "jar" important!
1834 jar.mustRunAfter cleanPackageDir
1835 syncJars.mustRunAfter cleanPackageDir
1836 dependsOn cleanPackageDir
1839 outputs.dir("${jalviewDir}/${package_dir}")
1844 dependsOn cleanPackageDir
1851 group = "distribution"
1852 description = "Create a single jar file with all dependency libraries merged. Can be run with java -jar"
1856 from ("${jalviewDir}/${libDistDir}") {
1860 attributes "Implementation-Version": JALVIEW_VERSION,
1861 "Application-Name": applicationName
1864 duplicatesStrategy "INCLUDE"
1866 mainClassName = shadow_jar_main_class
1868 classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
1873 task getdownWebsite() {
1874 group = "distribution"
1875 description = "Create the getdown minimal app folder, and website folder for this version of jalview. Website folder also used for offline app installer"
1880 def getdownWebsiteResourceFilenames = []
1881 def getdownResourceDir = getdownResourceDir
1882 def getdownResourceFilenames = []
1885 // clean the getdown website and files dir before creating getdown folders
1886 delete getdownAppBaseDir
1887 delete getdownFilesDir
1890 from buildProperties
1891 rename(file(buildProperties).getName(), getdown_build_properties)
1894 getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
1897 from channelPropsFile
1898 into getdownAppBaseDir
1900 getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
1902 // set some getdownTxt_ properties then go through all properties looking for getdownTxt_...
1903 def props = project.properties.sort { it.key }
1904 if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
1905 props.put("getdown_txt_java_min_version", getdownAltJavaMinVersion)
1907 if (getdownAltJavaMaxVersion != null && getdownAltJavaMaxVersion.length() > 0) {
1908 props.put("getdown_txt_java_max_version", getdownAltJavaMaxVersion)
1910 if (getdownAltMultiJavaLocation != null && getdownAltMultiJavaLocation.length() > 0) {
1911 props.put("getdown_txt_multi_java_location", getdownAltMultiJavaLocation)
1913 if (getdownImagesDir != null && file(getdownImagesDir).exists()) {
1914 props.put("getdown_txt_ui.background_image", "${getdownImagesDir}/${getdown_background_image}")
1915 props.put("getdown_txt_ui.instant_background_image", "${getdownImagesDir}/${getdown_instant_background_image}")
1916 props.put("getdown_txt_ui.error_background", "${getdownImagesDir}/${getdown_error_background}")
1917 props.put("getdown_txt_ui.progress_image", "${getdownImagesDir}/${getdown_progress_image}")
1918 props.put("getdown_txt_ui.icon", "${getdownImagesDir}/${getdown_icon}")
1919 props.put("getdown_txt_ui.mac_dock_icon", "${getdownImagesDir}/${getdown_mac_dock_icon}")
1922 props.put("getdown_txt_title", jalview_name)
1923 props.put("getdown_txt_ui.name", applicationName)
1925 // start with appbase
1926 getdownTextLines += "appbase = ${getdownAppBase}"
1927 props.each{ prop, val ->
1928 if (prop.startsWith("getdown_txt_") && val != null) {
1929 if (prop.startsWith("getdown_txt_multi_")) {
1930 def key = prop.substring(18)
1931 val.split(",").each{ v ->
1932 def line = "${key} = ${v}"
1933 getdownTextLines += line
1936 // file values rationalised
1937 if (val.indexOf('/') > -1 || prop.startsWith("getdown_txt_resource")) {
1939 if (val.indexOf('/') == 0) {
1942 } else if (val.indexOf('/') > 0) {
1943 // relative path (relative to jalviewDir)
1944 r = file( "${jalviewDir}/${val}" )
1947 val = "${getdown_resource_dir}/" + r.getName()
1948 getdownWebsiteResourceFilenames += val
1949 getdownResourceFilenames += r.getPath()
1952 if (! prop.startsWith("getdown_txt_resource")) {
1953 def line = prop.substring(12) + " = ${val}"
1954 getdownTextLines += line
1960 getdownWebsiteResourceFilenames.each{ filename ->
1961 getdownTextLines += "resource = ${filename}"
1963 getdownResourceFilenames.each{ filename ->
1966 into getdownResourceDir
1970 def getdownWrapperScripts = [ getdown_bash_wrapper_script, getdown_powershell_wrapper_script, getdown_batch_wrapper_script ]
1971 getdownWrapperScripts.each{ script ->
1972 def s = file( "${jalviewDir}/utils/getdown/${getdown_wrapper_script_dir}/${script}" )
1976 into "${getdownAppBaseDir}/${getdown_wrapper_script_dir}"
1978 getdownTextLines += "resource = ${getdown_wrapper_script_dir}/${script}"
1983 fileTree(file(package_dir)).each{ f ->
1984 if (f.isDirectory()) {
1985 def files = fileTree(dir: f, include: ["*"]).getFiles()
1987 } else if (f.exists()) {
1991 def jalviewJar = jar.archiveFileName.getOrNull()
1992 // put jalview.jar first for CLASSPATH and .properties files reasons
1993 codeFiles.sort{a, b -> ( a.getName() == jalviewJar ? -1 : ( b.getName() == jalviewJar ? 1 : a <=> b ) ) }.each{f ->
1994 def name = f.getName()
1995 def line = "code = ${getdownAppDistDir}/${name}"
1996 getdownTextLines += line
2003 // NOT USING MODULES YET, EVERYTHING SHOULD BE IN dist
2005 if (JAVA_VERSION.equals("11")) {
2006 def j11libFiles = fileTree(dir: "${jalviewDir}/${j11libDir}", include: ["*.jar"]).getFiles()
2007 j11libFiles.sort().each{f ->
2008 def name = f.getName()
2009 def line = "code = ${getdown_j11lib_dir}/${name}"
2010 getdownTextLines += line
2013 into getdownJ11libDir
2019 // 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.
2020 //getdownTextLines += "class = " + file(getdownLauncher).getName()
2021 getdownTextLines += "resource = ${getdown_launcher_new}"
2022 getdownTextLines += "class = ${main_class}"
2023 // Not setting these properties in general so that getdownappbase and getdowndistdir will default to release version in jalview.bin.Cache
2024 if (getdownSetAppBaseProperty) {
2025 getdownTextLines += "jvmarg = -Dgetdowndistdir=${getdownAppDistDir}"
2026 getdownTextLines += "jvmarg = -Dgetdownappbase=${getdownAppBase}"
2029 def getdownTxt = file("${getdownAppBaseDir}/getdown.txt")
2030 getdownTxt.write(getdownTextLines.join("\n"))
2032 getdownLaunchJvl = getdown_launch_jvl_name + ( (jvlChannelName != null && jvlChannelName.length() > 0)?"-${jvlChannelName}":"" ) + ".jvl"
2033 def launchJvl = file("${getdownAppBaseDir}/${getdownLaunchJvl}")
2034 launchJvl.write("appbase=${getdownAppBase}")
2036 // files going into the getdown website dir: getdown-launcher.jar
2038 from getdownLauncher
2039 rename(file(getdownLauncher).getName(), getdown_launcher_new)
2040 into getdownAppBaseDir
2043 // files going into the getdown website dir: getdown-launcher(-local).jar
2045 from getdownLauncher
2046 if (file(getdownLauncher).getName() != getdown_launcher) {
2047 rename(file(getdownLauncher).getName(), getdown_launcher)
2049 into getdownAppBaseDir
2052 // files going into the getdown website dir: ./install dir and files
2053 if (! (CHANNEL.startsWith("ARCHIVE") || CHANNEL.startsWith("DEVELOP"))) {
2056 from getdownLauncher
2057 from "${getdownAppDir}/${getdown_build_properties}"
2058 if (file(getdownLauncher).getName() != getdown_launcher) {
2059 rename(file(getdownLauncher).getName(), getdown_launcher)
2061 into getdownInstallDir
2064 // and make a copy in the getdown files dir (these are not downloaded by getdown)
2066 from getdownInstallDir
2067 into getdownFilesInstallDir
2071 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2075 from getdownLauncher
2076 from "${getdownAppBaseDir}/${getdown_build_properties}"
2077 from "${getdownAppBaseDir}/${channel_props}"
2078 if (file(getdownLauncher).getName() != getdown_launcher) {
2079 rename(file(getdownLauncher).getName(), getdown_launcher)
2081 into getdownFilesDir
2084 // and ./resource (not all downloaded by getdown)
2086 from getdownResourceDir
2087 into "${getdownFilesDir}/${getdown_resource_dir}"
2092 inputs.dir("${jalviewDir}/${package_dir}")
2094 outputs.dir(getdownAppBaseDir)
2095 outputs.dir(getdownFilesDir)
2099 // a helper task to allow getdown digest of any dir: `gradle getdownDigestDir -PDIGESTDIR=/path/to/my/random/getdown/dir
2100 task getdownDigestDir(type: JavaExec) {
2102 description "A task to run a getdown Digest on a dir with getdown.txt. Provide a DIGESTDIR property via -PDIGESTDIR=..."
2104 def digestDirPropertyName = "DIGESTDIR"
2106 classpath = files(getdownLauncher)
2107 def digestDir = findProperty(digestDirPropertyName)
2108 if (digestDir == null) {
2109 throw new GradleException("Must provide a DIGESTDIR value to produce an alternative getdown digest")
2113 main = "com.threerings.getdown.tools.Digester"
2117 task getdownDigest(type: JavaExec) {
2118 group = "distribution"
2119 description = "Digest the getdown website folder"
2120 dependsOn getdownWebsite
2122 classpath = files(getdownLauncher)
2124 main = "com.threerings.getdown.tools.Digester"
2125 args getdownAppBaseDir
2126 inputs.dir(getdownAppBaseDir)
2127 outputs.file("${getdownAppBaseDir}/digest2.txt")
2132 group = "distribution"
2133 description = "Create the minimal and full getdown app folder for installers and website and create digest file"
2134 dependsOn getdownDigest
2136 if (reportRsyncCommand) {
2137 def fromDir = getdownAppBaseDir + (getdownAppBaseDir.endsWith('/')?'':'/')
2138 def toDir = "${getdown_rsync_dest}/${getdownDir}" + (getdownDir.endsWith('/')?'':'/')
2139 println "LIKELY RSYNC COMMAND:"
2140 println "mkdir -p '$toDir'\nrsync -avh --delete '$fromDir' '$toDir'"
2141 if (RUNRSYNC == "true") {
2143 commandLine "mkdir", "-p", toDir
2146 commandLine "rsync", "-avh", "--delete", fromDir, toDir
2154 task getdownArchiveBuild() {
2155 group = "distribution"
2156 description = "Put files in the archive dir to go on the website"
2158 dependsOn getdownWebsite
2160 def v = "v${JALVIEW_VERSION_UNDERSCORES}"
2161 def vDir = "${getdownArchiveDir}/${v}"
2162 getdownFullArchiveDir = "${vDir}/getdown"
2163 getdownVersionLaunchJvl = "${vDir}/jalview-${v}.jvl"
2165 def vAltDir = "alt_${v}"
2166 def archiveImagesDir = "${jalviewDir}/${channel_properties_dir}/old/images"
2169 // cleanup old "old" dir
2170 delete getdownArchiveDir
2172 def getdownArchiveTxt = file("${getdownFullArchiveDir}/getdown.txt")
2173 getdownArchiveTxt.getParentFile().mkdirs()
2174 def getdownArchiveTextLines = []
2175 def getdownFullArchiveAppBase = "${getdownArchiveAppBase}${getdownArchiveAppBase.endsWith("/")?"":"/"}${v}/getdown/"
2179 from "${getdownAppBaseDir}/${getdownAppDistDir}"
2180 into "${getdownFullArchiveDir}/${vAltDir}"
2183 getdownTextLines.each { line ->
2184 line = line.replaceAll("^(?<s>appbase\\s*=\\s*).*", '${s}'+getdownFullArchiveAppBase)
2185 line = line.replaceAll("^(?<s>(resource|code)\\s*=\\s*)${getdownAppDistDir}/", '${s}'+vAltDir+"/")
2186 line = line.replaceAll("^(?<s>ui.background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background.png")
2187 line = line.replaceAll("^(?<s>ui.instant_background_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_initialising.png")
2188 line = line.replaceAll("^(?<s>ui.error_background\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_background_error.png")
2189 line = line.replaceAll("^(?<s>ui.progress_image\\s*=\\s*).*\\.png", '${s}'+"${getdown_resource_dir}/jalview_archive_getdown_progress_bar.png")
2190 // remove the existing resource = resource/ or bin/ lines
2191 if (! line.matches("resource\\s*=\\s*(resource|bin)/.*")) {
2192 getdownArchiveTextLines += line
2196 // the resource dir -- add these files as resource lines in getdown.txt
2198 from "${archiveImagesDir}"
2199 into "${getdownFullArchiveDir}/${getdown_resource_dir}"
2201 getdownArchiveTextLines += "resource = ${getdown_resource_dir}/${file.getName()}"
2205 getdownArchiveTxt.write(getdownArchiveTextLines.join("\n"))
2207 def vLaunchJvl = file(getdownVersionLaunchJvl)
2208 vLaunchJvl.getParentFile().mkdirs()
2209 vLaunchJvl.write("appbase=${getdownFullArchiveAppBase}\n")
2210 def vLaunchJvlPath = vLaunchJvl.toPath().toAbsolutePath()
2211 def jvlLinkPath = file("${vDir}/jalview.jvl").toPath().toAbsolutePath()
2212 // for some reason filepath.relativize(fileInSameDirPath) gives a path to "../" which is wrong
2213 //java.nio.file.Files.createSymbolicLink(jvlLinkPath, jvlLinkPath.relativize(vLaunchJvlPath));
2214 java.nio.file.Files.createSymbolicLink(jvlLinkPath, java.nio.file.Paths.get(".",vLaunchJvl.getName()));
2216 // files going into the getdown files dir: getdown.txt, getdown-launcher.jar, channel-launch.jvl, build_properties
2218 from getdownLauncher
2219 from "${getdownAppBaseDir}/${getdownLaunchJvl}"
2220 from "${getdownAppBaseDir}/${getdown_launcher_new}"
2221 from "${getdownAppBaseDir}/${channel_props}"
2222 if (file(getdownLauncher).getName() != getdown_launcher) {
2223 rename(file(getdownLauncher).getName(), getdown_launcher)
2225 into getdownFullArchiveDir
2231 task getdownArchiveDigest(type: JavaExec) {
2232 group = "distribution"
2233 description = "Digest the getdown archive folder"
2235 dependsOn getdownArchiveBuild
2238 classpath = files(getdownLauncher)
2239 args getdownFullArchiveDir
2241 main = "com.threerings.getdown.tools.Digester"
2242 inputs.dir(getdownFullArchiveDir)
2243 outputs.file("${getdownFullArchiveDir}/digest2.txt")
2246 task getdownArchive() {
2247 group = "distribution"
2248 description = "Build the website archive dir with getdown digest"
2250 dependsOn getdownArchiveBuild
2251 dependsOn getdownArchiveDigest
2254 tasks.withType(JavaCompile) {
2255 options.encoding = 'UTF-8'
2261 delete getdownAppBaseDir
2262 delete getdownFilesDir
2263 delete getdownArchiveDir
2269 if (file(install4jHomeDir).exists()) {
2271 } else if (file(System.getProperty("user.home")+"/buildtools/install4j").exists()) {
2272 install4jHomeDir = System.getProperty("user.home")+"/buildtools/install4j"
2273 } else if (file("/Applications/install4j.app/Contents/Resources/app").exists()) {
2274 install4jHomeDir = "/Applications/install4j.app/Contents/Resources/app"
2276 installDir(file(install4jHomeDir))
2278 mediaTypes = Arrays.asList(install4j_media_types.split(","))
2282 task copyInstall4jTemplate {
2283 def install4jTemplateFile = file("${install4jDir}/${install4j_template}")
2284 def install4jFileAssociationsFile = file("${install4jDir}/${install4j_installer_file_associations}")
2285 inputs.file(install4jTemplateFile)
2286 inputs.file(install4jFileAssociationsFile)
2287 inputs.property("CHANNEL", { CHANNEL })
2288 outputs.file(install4jConfFile)
2291 def install4jConfigXml = new XmlParser().parse(install4jTemplateFile)
2293 // turn off code signing if no OSX_KEYPASS
2294 if (OSX_KEYPASS == "") {
2295 install4jConfigXml.'**'.codeSigning.each { codeSigning ->
2296 codeSigning.'@macEnabled' = "false"
2298 install4jConfigXml.'**'.windows.each { windows ->
2299 windows.'@runPostProcessor' = "false"
2303 // disable install screen for OSX dmg (for 2.11.2.0)
2304 install4jConfigXml.'**'.macosArchive.each { macosArchive ->
2305 macosArchive.attributes().remove('executeSetupApp')
2306 macosArchive.attributes().remove('setupAppId')
2309 // turn off checksum creation for LOCAL channel
2310 def e = install4jConfigXml.application[0]
2311 e.'@createChecksums' = string(install4jCheckSums)
2313 // put file association actions where placeholder action is
2314 def install4jFileAssociationsText = install4jFileAssociationsFile.text
2315 def fileAssociationActions = new XmlParser().parseText("<actions>${install4jFileAssociationsText}</actions>")
2316 install4jConfigXml.'**'.action.any { a -> // .any{} stops after the first one that returns true
2317 if (a.'@name' == 'EXTENSIONS_REPLACED_BY_GRADLE') {
2318 def parent = a.parent()
2320 fileAssociationActions.each { faa ->
2323 // don't need to continue in .any loop once replacements have been made
2328 // use Windows Program Group with Examples folder for RELEASE, and Program Group without Examples for everything else
2329 // NB we're deleting the /other/ one!
2330 // Also remove the examples subdir from non-release versions
2331 def customizedIdToDelete = "PROGRAM_GROUP_RELEASE"
2332 // 2.11.1.0 NOT releasing with the Examples folder in the Program Group
2333 if (false && CHANNEL=="RELEASE") { // remove 'false && ' to include Examples folder in RELEASE channel
2334 customizedIdToDelete = "PROGRAM_GROUP_NON_RELEASE"
2336 // remove the examples subdir from Full File Set
2337 def files = install4jConfigXml.files[0]
2338 def fileset = files.filesets.fileset.find { fs -> fs.'@customizedId' == "FULL_FILE_SET" }
2339 def root = files.roots.root.find { r -> r.'@fileset' == fileset.'@id' }
2340 def mountPoint = files.mountPoints.mountPoint.find { mp -> mp.'@root' == root.'@id' }
2341 def dirEntry = files.entries.dirEntry.find { de -> de.'@mountPoint' == mountPoint.'@id' && de.'@subDirectory' == "examples" }
2342 dirEntry.parent().remove(dirEntry)
2344 install4jConfigXml.'**'.action.any { a ->
2345 if (a.'@customizedId' == customizedIdToDelete) {
2346 def parent = a.parent()
2352 // write install4j file
2353 install4jConfFile.text = XmlUtil.serialize(install4jConfigXml)
2360 delete install4jConfFile
2364 task cleanInstallersDataFiles {
2365 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2366 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2367 def hugoDataJsonFile = file("${jalviewDir}/${install4jBuildDir}/installers-${JALVIEW_VERSION_UNDERSCORES}.json")
2369 delete installersOutputTxt
2370 delete installersSha256
2371 delete hugoDataJsonFile
2375 task installerFiles(type: com.install4j.gradle.Install4jTask) {
2376 group = "distribution"
2377 description = "Create the install4j installers"
2379 dependsOn copyInstall4jTemplate
2380 dependsOn cleanInstallersDataFiles
2382 projectFile = install4jConfFile
2384 // create an md5 for the input files to use as version for install4j conf file
2385 def digest = MessageDigest.getInstance("MD5")
2387 (file("${install4jDir}/${install4j_template}").text +
2388 file("${install4jDir}/${install4j_info_plist_file_associations}").text +
2389 file("${install4jDir}/${install4j_installer_file_associations}").text).bytes)
2390 def filesMd5 = new BigInteger(1, digest.digest()).toString(16)
2391 if (filesMd5.length() >= 8) {
2392 filesMd5 = filesMd5.substring(0,8)
2394 def install4jTemplateVersion = "${JALVIEW_VERSION}_F${filesMd5}_C${gitHash}"
2397 'JALVIEW_NAME': jalview_name,
2398 'JALVIEW_APPLICATION_NAME': applicationName,
2399 'JALVIEW_DIR': "../..",
2400 'OSX_KEYSTORE': OSX_KEYSTORE,
2401 'OSX_APPLEID': OSX_APPLEID,
2402 'OSX_ALTOOLPASS': OSX_ALTOOLPASS,
2403 'JSIGN_SH': JSIGN_SH,
2404 'JRE_DIR': getdown_app_dir_java,
2405 'INSTALLER_TEMPLATE_VERSION': install4jTemplateVersion,
2406 'JALVIEW_VERSION': JALVIEW_VERSION,
2407 'JAVA_MIN_VERSION': JAVA_MIN_VERSION,
2408 'JAVA_MAX_VERSION': JAVA_MAX_VERSION,
2409 'JAVA_VERSION': JAVA_VERSION,
2410 'JAVA_INTEGER_VERSION': JAVA_INTEGER_VERSION,
2411 'VERSION': JALVIEW_VERSION,
2412 'MACOS_JAVA_VM_DIR': macosJavaVMDir,
2413 'WINDOWS_JAVA_VM_DIR': windowsJavaVMDir,
2414 'LINUX_JAVA_VM_DIR': linuxJavaVMDir,
2415 'MACOS_JAVA_VM_TGZ': macosJavaVMTgz,
2416 'WINDOWS_JAVA_VM_TGZ': windowsJavaVMTgz,
2417 'LINUX_JAVA_VM_TGZ': linuxJavaVMTgz,
2418 'COPYRIGHT_MESSAGE': install4j_copyright_message,
2419 'BUNDLE_ID': install4jBundleId,
2420 'INTERNAL_ID': install4jInternalId,
2421 'WINDOWS_APPLICATION_ID': install4jWinApplicationId,
2422 'MACOS_DMG_DS_STORE': install4jDMGDSStore,
2423 'MACOS_DMG_BG_IMAGE': install4jDMGBackgroundImage,
2424 'WRAPPER_LINK': getdownWrapperLink,
2425 'BASH_WRAPPER_SCRIPT': getdown_bash_wrapper_script,
2426 'POWERSHELL_WRAPPER_SCRIPT': getdown_powershell_wrapper_script,
2427 'WRAPPER_SCRIPT_BIN_DIR': getdown_wrapper_script_dir,
2428 'INSTALLER_NAME': install4jInstallerName,
2429 'INSTALL4J_UTILS_DIR': install4j_utils_dir,
2430 'GETDOWN_CHANNEL_DIR': getdownChannelDir,
2431 'GETDOWN_FILES_DIR': getdown_files_dir,
2432 'GETDOWN_RESOURCE_DIR': getdown_resource_dir,
2433 'GETDOWN_DIST_DIR': getdownAppDistDir,
2434 'GETDOWN_ALT_DIR': getdown_app_dir_alt,
2435 'GETDOWN_INSTALL_DIR': getdown_install_dir,
2436 'INFO_PLIST_FILE_ASSOCIATIONS_FILE': install4j_info_plist_file_associations,
2437 'BUILD_DIR': install4jBuildDir,
2438 'APPLICATION_CATEGORIES': install4j_application_categories,
2439 'APPLICATION_FOLDER': install4jApplicationFolder,
2440 'UNIX_APPLICATION_FOLDER': install4jUnixApplicationFolder,
2441 'EXECUTABLE_NAME': install4jExecutableName,
2442 'EXTRA_SCHEME': install4jExtraScheme,
2443 'MAC_ICONS_FILE': install4jMacIconsFile,
2444 'WINDOWS_ICONS_FILE': install4jWindowsIconsFile,
2445 'PNG_ICON_FILE': install4jPngIconFile,
2446 'BACKGROUND': install4jBackground,
2450 //println("INSTALL4J VARIABLES:")
2451 //variables.each{k,v->println("${k}=${v}")}
2453 destination = "${jalviewDir}/${install4jBuildDir}"
2454 buildSelected = true
2456 if (install4j_faster.equals("true") || CHANNEL.startsWith("LOCAL")) {
2458 disableSigning = true
2459 disableNotarization = true
2463 macKeystorePassword = OSX_KEYPASS
2466 if (OSX_ALTOOLPASS) {
2467 appleIdPassword = OSX_ALTOOLPASS
2468 disableNotarization = false
2470 disableNotarization = true
2474 println("Using projectFile "+projectFile)
2475 if (!disableNotarization) { println("Will notarize OSX App DMG") }
2479 inputs.dir(getdownAppBaseDir)
2480 inputs.file(install4jConfFile)
2481 inputs.file("${install4jDir}/${install4j_info_plist_file_associations}")
2482 inputs.dir(macosJavaVMDir)
2483 inputs.dir(windowsJavaVMDir)
2484 outputs.dir("${jalviewDir}/${install4j_build_dir}/${JAVA_VERSION}")
2487 def getDataHash(File myFile) {
2488 HashCode hash = Files.asByteSource(myFile).hash(Hashing.sha256())
2489 return myFile.exists()
2491 "file" : myFile.getName(),
2492 "filesize" : myFile.length(),
2493 "sha256" : hash.toString()
2498 def writeDataJsonFile(File installersOutputTxt, File installersSha256, File dataJsonFile) {
2500 "channel" : getdownChannelName,
2501 "date" : getDate("yyyy-MM-dd HH:mm:ss"),
2502 "git-commit" : "${gitHash} [${gitBranch}]",
2503 "version" : JALVIEW_VERSION
2505 // install4j installer files
2506 if (installersOutputTxt.exists()) {
2508 installersOutputTxt.readLines().each { def line ->
2509 if (line.startsWith("#")) {
2512 line.replaceAll("\n","")
2513 def vals = line.split("\t")
2514 def filename = vals[3]
2515 def filesize = file(filename).length()
2516 filename = filename.replaceAll(/^.*\//, "")
2517 hash[vals[0]] = [ "id" : vals[0], "os" : vals[1], "name" : vals[2], "file" : filename, "filesize" : filesize ]
2518 idHash."${filename}" = vals[0]
2520 if (install4jCheckSums && installersSha256.exists()) {
2521 installersSha256.readLines().each { def line ->
2522 if (line.startsWith("#")) {
2525 line.replaceAll("\n","")
2526 def vals = line.split(/\s+\*?/)
2527 def filename = vals[1]
2528 def innerHash = (hash.(idHash."${filename}"))."sha256" = vals[0]
2534 "JAR": shadowJar.archiveFile, // executable JAR
2535 "JVL": getdownVersionLaunchJvl, // version JVL
2536 "SOURCE": sourceDist.archiveFile // source TGZ
2537 ].each { key, value ->
2538 def file = file(value)
2539 if (file.exists()) {
2540 def fileHash = getDataHash(file)
2541 if (fileHash != null) {
2542 hash."${key}" = fileHash;
2546 return dataJsonFile.write(new JsonBuilder(hash).toPrettyString())
2549 task staticMakeInstallersJsonFile {
2551 def output = findProperty("i4j_output")
2552 def sha256 = findProperty("i4j_sha256")
2553 def json = findProperty("i4j_json")
2554 if (output == null || sha256 == null || json == null) {
2555 throw new GradleException("Must provide paths to all of output.txt, sha256sums, and output.json with '-Pi4j_output=... -Pi4j_sha256=... -Pi4j_json=...")
2557 writeDataJsonFile(file(output), file(sha256), file(json))
2562 dependsOn installerFiles
2568 eclipse().configFile(eclipse_codestyle_file)
2572 task createSourceReleaseProperties(type: WriteProperties) {
2573 group = "distribution"
2574 description = "Create the source RELEASE properties file"
2576 def sourceTarBuildDir = "${buildDir}/sourceTar"
2577 def sourceReleasePropertiesFile = "${sourceTarBuildDir}/RELEASE"
2578 outputFile (sourceReleasePropertiesFile)
2581 releaseProps.each{ key, val -> property key, val }
2582 property "git.branch", gitBranch
2583 property "git.hash", gitHash
2586 outputs.file(outputFile)
2589 task sourceDist(type: Tar) {
2590 group "distribution"
2591 description "Create a source .tar.gz file for distribution"
2593 dependsOn createBuildProperties
2594 dependsOn convertMdFiles
2595 dependsOn eclipseAllPreferences
2596 dependsOn createSourceReleaseProperties
2599 def outputFileName = "${project.name}_${JALVIEW_VERSION_UNDERSCORES}.tar.gz"
2600 archiveFileName = outputFileName
2602 compression Compression.GZIP
2617 "**/*.class","$j11modDir/**/*.jar","appletlib","**/*locales",
2619 "utils/InstallAnywhere",
2634 "gradle.properties",
2646 ".settings/org.eclipse.buildship.core.prefs",
2647 ".settings/org.eclipse.jdt.core.prefs"
2651 exclude (EXCLUDE_FILES)
2652 include (PROCESS_FILES)
2653 filter(ReplaceTokens,
2657 'Version-Rel': JALVIEW_VERSION,
2658 'Year-Rel': getDate("yyyy")
2663 exclude (EXCLUDE_FILES)
2664 exclude (PROCESS_FILES)
2665 exclude ("appletlib")
2666 exclude ("**/*locales")
2667 exclude ("*locales/**")
2668 exclude ("utils/InstallAnywhere")
2670 exclude (getdown_files_dir)
2671 // getdown_website_dir and getdown_archive_dir moved to build/website/docroot/getdown
2672 //exclude (getdown_website_dir)
2673 //exclude (getdown_archive_dir)
2675 // exluding these as not using jars as modules yet
2676 exclude ("${j11modDir}/**/*.jar")
2679 include(INCLUDE_FILES)
2681 // from (jalviewDir) {
2682 // // explicit includes for stuff that seemed to not get included
2683 // include(fileTree("test/**/*."))
2684 // exclude(EXCLUDE_FILES)
2685 // exclude(PROCESS_FILES)
2688 from(file(buildProperties).getParent()) {
2689 include(file(buildProperties).getName())
2690 rename(file(buildProperties).getName(), "build_properties")
2692 line.replaceAll("^INSTALLATION=.*\$","INSTALLATION=Source Release"+" git-commit\\\\:"+gitHash+" ["+gitBranch+"]")
2696 def sourceTarBuildDir = "${buildDir}/sourceTar"
2697 from(sourceTarBuildDir) {
2698 // this includes the appended RELEASE properties file
2702 task dataInstallersJson {
2704 description "Create the installers-VERSION.json data file for installer files created"
2706 mustRunAfter installers
2707 mustRunAfter shadowJar
2708 mustRunAfter sourceDist
2709 mustRunAfter getdownArchive
2711 def installersOutputTxt = file("${jalviewDir}/${install4jBuildDir}/output.txt")
2712 def installersSha256 = file("${jalviewDir}/${install4jBuildDir}/sha256sums")
2714 if (installersOutputTxt.exists()) {
2715 inputs.file(installersOutputTxt)
2717 if (install4jCheckSums && installersSha256.exists()) {
2718 inputs.file(installersSha256)
2721 shadowJar.archiveFile, // executable JAR
2722 getdownVersionLaunchJvl, // version JVL
2723 sourceDist.archiveFile // source TGZ
2724 ].each { fileName ->
2725 if (file(fileName).exists()) {
2726 inputs.file(fileName)
2730 outputs.file(hugoDataJsonFile)
2733 writeDataJsonFile(installersOutputTxt, installersSha256, hugoDataJsonFile)
2739 description "Copies all help pages to build dir. Runs ant task 'pubhtmlhelp'."
2742 dependsOn pubhtmlhelp
2744 inputs.dir("${helpBuildDir}/${help_dir}")
2745 outputs.dir("${buildDir}/distributions/${help_dir}")
2749 task j2sSetHeadlessBuild {
2756 task jalviewjsEnableAltFileProperty(type: WriteProperties) {
2758 description "Enable the alternative J2S Config file for headless build"
2760 outputFile = jalviewjsJ2sSettingsFileName
2761 def j2sPropsFile = file(jalviewjsJ2sSettingsFileName)
2762 def j2sProps = new Properties()
2763 if (j2sPropsFile.exists()) {
2765 def j2sPropsFileFIS = new FileInputStream(j2sPropsFile)
2766 j2sProps.load(j2sPropsFileFIS)
2767 j2sPropsFileFIS.close()
2769 j2sProps.each { prop, val ->
2772 } catch (Exception e) {
2773 println("Exception reading ${jalviewjsJ2sSettingsFileName}")
2777 if (! j2sProps.stringPropertyNames().contains(jalviewjs_j2s_alt_file_property_config)) {
2778 property(jalviewjs_j2s_alt_file_property_config, jalviewjs_j2s_alt_file_property)
2783 task jalviewjsSetEclipseWorkspace {
2784 def propKey = "jalviewjs_eclipse_workspace"
2786 if (project.hasProperty(propKey)) {
2787 propVal = project.getProperty(propKey)
2788 if (propVal.startsWith("~/")) {
2789 propVal = System.getProperty("user.home") + propVal.substring(1)
2792 def propsFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_workspace_location_file}"
2793 def propsFile = file(propsFileName)
2794 def eclipseWsDir = propVal
2795 def props = new Properties()
2797 def writeProps = true
2798 if (( eclipseWsDir == null || !file(eclipseWsDir).exists() ) && propsFile.exists()) {
2799 def ins = new FileInputStream(propsFileName)
2802 if (props.getProperty(propKey, null) != null) {
2803 eclipseWsDir = props.getProperty(propKey)
2808 if (eclipseWsDir == null || !file(eclipseWsDir).exists()) {
2809 def tempDir = File.createTempDir()
2810 eclipseWsDir = tempDir.getAbsolutePath()
2813 eclipseWorkspace = file(eclipseWsDir)
2816 // do not run a headless transpile when we claim to be in Eclipse
2818 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2819 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2821 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2825 props.setProperty(propKey, eclipseWsDir)
2826 propsFile.parentFile.mkdirs()
2827 def bytes = new ByteArrayOutputStream()
2828 props.store(bytes, null)
2829 def propertiesString = bytes.toString()
2830 propsFile.text = propertiesString
2836 println("ECLIPSE WORKSPACE: "+eclipseWorkspace.getPath())
2839 //inputs.property(propKey, eclipseWsDir) // eclipseWsDir only gets set once this task runs, so will be out-of-date
2840 outputs.file(propsFileName)
2841 outputs.upToDateWhen { eclipseWorkspace.exists() && propsFile.exists() }
2845 task jalviewjsEclipsePaths {
2848 def eclipseRoot = jalviewjs_eclipse_root
2849 if (eclipseRoot.startsWith("~/")) {
2850 eclipseRoot = System.getProperty("user.home") + eclipseRoot.substring(1)
2852 if (OperatingSystem.current().isMacOsX()) {
2853 eclipseRoot += "/Eclipse.app"
2854 eclipseBinary = "${eclipseRoot}/Contents/MacOS/eclipse"
2855 eclipseProduct = "${eclipseRoot}/Contents/Eclipse/.eclipseproduct"
2856 } else if (OperatingSystem.current().isWindows()) { // check these paths!!
2857 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2858 eclipseRoot += "/eclipse"
2860 eclipseBinary = "${eclipseRoot}/eclipse.exe"
2861 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2862 } else { // linux or unix
2863 if (file("${eclipseRoot}/eclipse").isDirectory() && file("${eclipseRoot}/eclipse/.eclipseproduct").exists()) {
2864 eclipseRoot += "/eclipse"
2865 println("eclipseDir exists")
2867 eclipseBinary = "${eclipseRoot}/eclipse"
2868 eclipseProduct = "${eclipseRoot}/.eclipseproduct"
2871 eclipseVersion = "4.13" // default
2872 def assumedVersion = true
2873 if (file(eclipseProduct).exists()) {
2874 def fis = new FileInputStream(eclipseProduct)
2875 def props = new Properties()
2877 eclipseVersion = props.getProperty("version")
2879 assumedVersion = false
2882 def propKey = "eclipse_debug"
2883 eclipseDebug = (project.hasProperty(propKey) && project.getProperty(propKey).equals("true"))
2886 // do not run a headless transpile when we claim to be in Eclipse
2888 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2889 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
2891 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
2894 if (!assumedVersion) {
2895 println("ECLIPSE VERSION=${eclipseVersion}")
2901 task printProperties {
2903 description "Output to console all System.properties"
2905 System.properties.each { key, val -> System.out.println("Property: ${key}=${val}") }
2911 dependsOn eclipseProject
2912 dependsOn eclipseClasspath
2913 dependsOn eclipseJdt
2917 // this version (type: Copy) will delete anything in the eclipse dropins folder that isn't in fromDropinsDir
2918 task jalviewjsEclipseCopyDropins(type: Copy) {
2919 dependsOn jalviewjsEclipsePaths
2921 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
2922 inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
2923 def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
2930 // this eclipse -clean doesn't actually work
2931 task jalviewjsCleanEclipse(type: Exec) {
2932 dependsOn eclipseSetup
2933 dependsOn jalviewjsEclipsePaths
2934 dependsOn jalviewjsEclipseCopyDropins
2936 executable(eclipseBinary)
2937 args(["-nosplash", "--launcher.suppressErrors", "-data", eclipseWorkspace.getPath(), "-clean", "-console", "-consoleLog"])
2943 def inputString = """exit
2946 def inputByteStream = new ByteArrayInputStream(inputString.getBytes())
2947 standardInput = inputByteStream
2950 /* not really working yet
2951 jalviewjsEclipseCopyDropins.finalizedBy jalviewjsCleanEclipse
2955 task jalviewjsTransferUnzipSwingJs {
2956 def file_zip = "${jalviewDir}/${jalviewjs_swingjs_zip}"
2960 from zipTree(file_zip)
2961 into "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2965 inputs.file file_zip
2966 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
2970 task jalviewjsTransferUnzipLib {
2971 def zipFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_libjs_dir}", include: "*.zip")
2974 zipFiles.each { file_zip ->
2976 from zipTree(file_zip)
2977 into "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2982 inputs.files zipFiles
2983 outputs.dir "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
2987 task jalviewjsTransferUnzipAllLibs {
2988 dependsOn jalviewjsTransferUnzipSwingJs
2989 dependsOn jalviewjsTransferUnzipLib
2993 task jalviewjsCreateJ2sSettings(type: WriteProperties) {
2995 description "Create the alternative j2s file from the j2s.* properties"
2997 jalviewjsJ2sProps = project.properties.findAll { it.key.startsWith("j2s.") }.sort { it.key }
2998 def siteDirProperty = "j2s.site.directory"
2999 def setSiteDir = false
3000 jalviewjsJ2sProps.each { prop, val ->
3002 if (prop == siteDirProperty) {
3003 if (!(val.startsWith('/') || val.startsWith("file://") )) {
3004 val = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${val}"
3010 if (!setSiteDir) { // default site location, don't override specifically set property
3011 property(siteDirProperty,"${jalviewDirRelativePath}/${jalviewjsTransferSiteJsDir}")
3014 outputFile = jalviewjsJ2sAltSettingsFileName
3017 inputs.properties(jalviewjsJ2sProps)
3018 outputs.file(jalviewjsJ2sAltSettingsFileName)
3023 task jalviewjsEclipseSetup {
3024 dependsOn jalviewjsEclipseCopyDropins
3025 dependsOn jalviewjsSetEclipseWorkspace
3026 dependsOn jalviewjsCreateJ2sSettings
3030 task jalviewjsSyncAllLibs (type: Sync) {
3031 dependsOn jalviewjsTransferUnzipAllLibs
3032 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
3033 inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
3034 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3038 def outputFiles = []
3039 rename { filename ->
3040 outputFiles += "${outputDir}/${filename}"
3047 // should this be exclude really ?
3048 duplicatesStrategy "INCLUDE"
3050 outputs.files outputFiles
3051 inputs.files inputFiles
3055 task jalviewjsSyncResources (type: Sync) {
3056 dependsOn buildResources
3058 def inputFiles = fileTree(dir: resourcesBuildDir)
3059 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3063 def outputFiles = []
3064 rename { filename ->
3065 outputFiles += "${outputDir}/${filename}"
3071 outputs.files outputFiles
3072 inputs.files inputFiles
3076 task jalviewjsSyncSiteResources (type: Sync) {
3077 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
3078 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3082 def outputFiles = []
3083 rename { filename ->
3084 outputFiles += "${outputDir}/${filename}"
3090 outputs.files outputFiles
3091 inputs.files inputFiles
3095 task jalviewjsSyncBuildProperties (type: Sync) {
3096 dependsOn createBuildProperties
3097 def inputFiles = [file(buildProperties)]
3098 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
3102 def outputFiles = []
3103 rename { filename ->
3104 outputFiles += "${outputDir}/${filename}"
3110 outputs.files outputFiles
3111 inputs.files inputFiles
3115 task jalviewjsProjectImport(type: Exec) {
3116 dependsOn eclipseSetup
3117 dependsOn jalviewjsEclipsePaths
3118 dependsOn jalviewjsEclipseSetup
3121 // do not run a headless import when we claim to be in Eclipse
3123 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3124 throw new StopExecutionException("Not running headless import whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3126 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3130 //def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview/org.eclipse.jdt.core"
3131 def projdir = eclipseWorkspace.getPath()+"/.metadata/.plugins/org.eclipse.core.resources/.projects/jalview"
3132 executable(eclipseBinary)
3133 args(["-nosplash", "--launcher.suppressErrors", "-application", "com.seeq.eclipse.importprojects.headlessimport", "-data", eclipseWorkspace.getPath(), "-import", jalviewDirAbsolutePath])
3137 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3139 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3140 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3143 inputs.file("${jalviewDir}/.project")
3144 outputs.upToDateWhen {
3145 file(projdir).exists()
3150 task jalviewjsTranspile(type: Exec) {
3151 dependsOn jalviewjsEclipseSetup
3152 dependsOn jalviewjsProjectImport
3153 dependsOn jalviewjsEclipsePaths
3155 dependsOn jalviewjsEnableAltFileProperty
3159 // do not run a headless transpile when we claim to be in Eclipse
3161 println("Skipping task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3162 throw new StopExecutionException("Not running headless transpile whilst IN_ECLIPSE is '${IN_ECLIPSE}'")
3164 println("Running task ${name} as IN_ECLIPSE=${IN_ECLIPSE}")
3168 executable(eclipseBinary)
3169 args(["-nosplash", "--launcher.suppressErrors", "-application", "org.eclipse.jdt.apt.core.aptBuild", "-data", eclipseWorkspace, "-${jalviewjs_eclipse_build_arg}", eclipse_project_name ])
3173 args += [ "--launcher.appendVmargs", "-vmargs", "-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}" ]
3175 args += [ "-D${j2sHeadlessBuildProperty}=true" ]
3176 args += [ "-D${jalviewjs_j2s_alt_file_property}=${jalviewjsJ2sAltSettingsFileName}" ]
3182 stdout = new ByteArrayOutputStream()
3183 stderr = new ByteArrayOutputStream()
3185 def logOutFileName = "${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}"
3186 def logOutFile = file(logOutFileName)
3187 logOutFile.createNewFile()
3188 logOutFile.text = """ROOT: ${jalviewjs_eclipse_root}
3189 BINARY: ${eclipseBinary}
3190 VERSION: ${eclipseVersion}
3191 WORKSPACE: ${eclipseWorkspace}
3192 DEBUG: ${eclipseDebug}
3195 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3196 // combine stdout and stderr
3197 def logErrFOS = logOutFOS
3199 if (jalviewjs_j2s_to_console.equals("true")) {
3200 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3201 new org.apache.tools.ant.util.TeeOutputStream(
3205 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3206 new org.apache.tools.ant.util.TeeOutputStream(
3211 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3214 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3221 if (stdout.toString().contains("Error processing ")) {
3222 // j2s did not complete transpile
3223 //throw new TaskExecutionException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3224 if (jalviewjs_ignore_transpile_errors.equals("true")) {
3225 println("IGNORING TRANSPILE ERRORS")
3226 println("See eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3228 throw new GradleException("Error during transpilation:\n${stderr}\nSee eclipse transpile log file '${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_j2s_transpile_stdout}'")
3233 inputs.dir("${jalviewDir}/${sourceDir}")
3234 outputs.dir("${jalviewDir}/${jalviewjsTransferSiteJsDir}")
3235 outputs.upToDateWhen( { file("${jalviewDir}/${jalviewjsTransferSiteJsDir}${jalviewjs_server_resource}").exists() } )
3239 def jalviewjsCallCore(String name, FileCollection list, String prefixFile, String suffixFile, String jsfile, String zjsfile, File logOutFile, Boolean logOutConsole) {
3241 def stdout = new ByteArrayOutputStream()
3242 def stderr = new ByteArrayOutputStream()
3244 def coreFile = file(jsfile)
3246 msg = "Creating core for ${name}...\nGenerating ${jsfile}"
3248 logOutFile.createNewFile()
3249 logOutFile.append(msg+"\n")
3251 def coreTop = file(prefixFile)
3252 def coreBottom = file(suffixFile)
3253 coreFile.getParentFile().mkdirs()
3254 coreFile.createNewFile()
3255 coreFile.write( coreTop.getText("UTF-8") )
3259 def t = f.getText("UTF-8")
3260 t.replaceAll("Clazz\\.([^_])","Clazz_${1}")
3261 coreFile.append( t )
3263 msg = "...file '"+f.getPath()+"' does not exist, skipping"
3265 logOutFile.append(msg+"\n")
3268 coreFile.append( coreBottom.getText("UTF-8") )
3270 msg = "Generating ${zjsfile}"
3272 logOutFile.append(msg+"\n")
3273 def logOutFOS = new FileOutputStream(logOutFile, true) // true == append
3274 def logErrFOS = logOutFOS
3277 classpath = files(["${jalviewDir}/${jalviewjs_closure_compiler}"])
3278 main = "com.google.javascript.jscomp.CommandLineRunner"
3279 jvmArgs = [ "-Dfile.encoding=UTF-8" ]
3280 args = [ "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--charset", "UTF-8", "--js", jsfile, "--js_output_file", zjsfile ]
3283 msg = "\nRunning '"+commandLine.join(' ')+"'\n"
3285 logOutFile.append(msg+"\n")
3287 if (logOutConsole) {
3288 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3289 new org.apache.tools.ant.util.TeeOutputStream(
3293 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3294 new org.apache.tools.ant.util.TeeOutputStream(
3299 standardOutput = new org.apache.tools.ant.util.TeeOutputStream(
3302 errorOutput = new org.apache.tools.ant.util.TeeOutputStream(
3309 logOutFile.append(msg+"\n")
3313 task jalviewjsBuildAllCores {
3315 description "Build the core js lib closures listed in the classlists dir"
3316 dependsOn jalviewjsTranspile
3317 dependsOn jalviewjsTransferUnzipSwingJs
3319 def j2sDir = "${jalviewDir}/${jalviewjsTransferSiteJsDir}/${jalviewjs_j2s_subdir}"
3320 def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
3321 def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
3322 def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
3323 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
3324 def prefixFile = "${jsDir}/core/coretop2.js"
3325 def suffixFile = "${jsDir}/core/corebottom2.js"
3327 inputs.file prefixFile
3328 inputs.file suffixFile
3330 def classlistFiles = []
3331 // add the classlists found int the jalviewjs_classlists_dir
3332 fileTree(dir: "${jalviewDir}/${jalviewjs_classlists_dir}", include: "*.txt").each {
3334 def name = file.getName() - ".txt"
3341 // _jmol and _jalview cores. Add any other peculiar classlist.txt files here
3342 //classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jmol}"), 'name': "_jvjmol" ]
3343 classlistFiles += [ 'file': file("${jalviewDir}/${jalviewjs_classlist_jalview}"), 'name': jalviewjsJalviewCoreName ]
3345 jalviewjsCoreClasslists = []
3347 classlistFiles.each {
3350 def file = hash['file']
3351 if (! file.exists()) {
3352 //println("...classlist file '"+file.getPath()+"' does not exist, skipping")
3353 return false // this is a "continue" in groovy .each closure
3355 def name = hash['name']
3357 name = file.getName() - ".txt"
3365 def list = fileTree(dir: j2sDir, includes: filelist)
3367 def jsfile = "${outputDir}/core${name}.js"
3368 def zjsfile = "${outputDir}/core${name}.z.js"
3370 jalviewjsCoreClasslists += [
3379 outputs.file(jsfile)
3380 outputs.file(zjsfile)
3383 // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
3384 def stevesoftClasslistName = "_stevesoft"
3385 def stevesoftClasslist = [
3386 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
3387 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
3388 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
3389 'name': stevesoftClasslistName
3391 jalviewjsCoreClasslists += stevesoftClasslist
3392 inputs.files(stevesoftClasslist['list'])
3393 outputs.file(stevesoftClasslist['jsfile'])
3394 outputs.file(stevesoftClasslist['zjsfile'])
3397 def allClasslistName = "_all"
3398 def allJsFiles = fileTree(dir: j2sDir, include: "**/*.js")
3399 allJsFiles += fileTree(
3403 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3404 "**/org/jmol/jvxl/readers/IsoIntersectFileReader.js",
3405 "**/org/jmol/export/JSExporter.js"
3408 allJsFiles += fileTree(
3412 // these exlusions are files that the closure-compiler produces errors for. Should fix them
3413 "**/sun/misc/Unsafe.js",
3414 "**/swingjs/jquery/jquery-editable-select.js",
3415 "**/swingjs/jquery/j2sComboBox.js",
3416 "**/sun/misc/FloatingDecimal.js"
3419 def allClasslist = [
3420 'jsfile': "${outputDir}/core${allClasslistName}.js",
3421 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
3423 'name': allClasslistName
3425 // not including this version of "all" core at the moment
3426 //jalviewjsCoreClasslists += allClasslist
3427 inputs.files(allClasslist['list'])
3428 outputs.file(allClasslist['jsfile'])
3429 outputs.file(allClasslist['zjsfile'])
3432 def logOutFile = file("${jalviewDirAbsolutePath}/${jalviewjsBuildDir}/${jalviewjs_j2s_closure_stdout}")
3433 logOutFile.getParentFile().mkdirs()
3434 logOutFile.createNewFile()
3435 logOutFile.write(getDate("yyyy-MM-dd HH:mm:ss")+" jalviewjsBuildAllCores\n----\n")
3437 jalviewjsCoreClasslists.each {
3438 jalviewjsCallCore(it.name, it.list, prefixFile, suffixFile, it.jsfile, it.zjsfile, logOutFile, jalviewjs_j2s_to_console.equals("true"))
3445 def jalviewjsPublishCoreTemplate(String coreName, String templateName, File inputFile, String outputFile) {
3448 into file(outputFile).getParentFile()
3449 rename { filename ->
3450 if (filename.equals(inputFile.getName())) {
3451 return file(outputFile).getName()
3455 filter(ReplaceTokens,
3459 'MAIN': '"'+main_class+'"',
3461 'NAME': jalviewjsJalviewTemplateName+" [core ${coreName}]",
3462 'COREKEY': jalviewjs_core_key,
3463 'CORENAME': coreName
3470 task jalviewjsPublishCoreTemplates {
3471 dependsOn jalviewjsBuildAllCores
3472 def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
3473 def inputFile = file(inputFileName)
3474 def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3476 def outputFiles = []
3477 jalviewjsCoreClasslists.each { cl ->
3478 def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
3479 cl['outputfile'] = outputFile
3480 outputFiles += outputFile
3484 jalviewjsCoreClasslists.each { cl ->
3485 jalviewjsPublishCoreTemplate(cl.name, jalviewjsJalviewTemplateName, inputFile, cl.outputfile)
3488 inputs.file(inputFile)
3489 outputs.files(outputFiles)
3493 task jalviewjsSyncCore (type: Sync) {
3494 dependsOn jalviewjsBuildAllCores
3495 dependsOn jalviewjsPublishCoreTemplates
3496 def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
3497 def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
3501 def outputFiles = []
3502 rename { filename ->
3503 outputFiles += "${outputDir}/${filename}"
3509 outputs.files outputFiles
3510 inputs.files inputFiles
3514 // this Copy version of TransferSiteJs will delete anything else in the target dir
3515 task jalviewjsCopyTransferSiteJs(type: Copy) {
3516 dependsOn jalviewjsTranspile
3517 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3518 into "${jalviewDir}/${jalviewjsSiteDir}"
3522 // this Sync version of TransferSite is used by buildship to keep the website automatically up to date when a file changes
3523 task jalviewjsSyncTransferSiteJs(type: Sync) {
3524 from "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3526 into "${jalviewDir}/${jalviewjsSiteDir}"
3533 jalviewjsSyncAllLibs.mustRunAfter jalviewjsCopyTransferSiteJs
3534 jalviewjsSyncResources.mustRunAfter jalviewjsCopyTransferSiteJs
3535 jalviewjsSyncSiteResources.mustRunAfter jalviewjsCopyTransferSiteJs
3536 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsCopyTransferSiteJs
3538 jalviewjsSyncAllLibs.mustRunAfter jalviewjsSyncTransferSiteJs
3539 jalviewjsSyncResources.mustRunAfter jalviewjsSyncTransferSiteJs
3540 jalviewjsSyncSiteResources.mustRunAfter jalviewjsSyncTransferSiteJs
3541 jalviewjsSyncBuildProperties.mustRunAfter jalviewjsSyncTransferSiteJs
3544 task jalviewjsPrepareSite {
3546 description "Prepares the website folder including unzipping files and copying resources"
3547 dependsOn jalviewjsSyncAllLibs
3548 dependsOn jalviewjsSyncResources
3549 dependsOn jalviewjsSyncSiteResources
3550 dependsOn jalviewjsSyncBuildProperties
3551 dependsOn jalviewjsSyncCore
3555 task jalviewjsBuildSite {
3557 description "Builds the whole website including transpiled code"
3558 dependsOn jalviewjsCopyTransferSiteJs
3559 dependsOn jalviewjsPrepareSite
3563 task cleanJalviewjsTransferSite {
3565 delete "${jalviewDir}/${jalviewjsTransferSiteJsDir}"
3566 delete "${jalviewDir}/${jalviewjsTransferSiteLibDir}"
3567 delete "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}"
3568 delete "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
3573 task cleanJalviewjsSite {
3574 dependsOn cleanJalviewjsTransferSite
3576 delete "${jalviewDir}/${jalviewjsSiteDir}"
3581 task jalviewjsSiteTar(type: Tar) {
3583 description "Creates a tar.gz file for the website"
3584 dependsOn jalviewjsBuildSite
3585 def outputFilename = "jalviewjs-site-${JALVIEW_VERSION}.tar.gz"
3586 archiveFileName = outputFilename
3588 compression Compression.GZIP
3590 from "${jalviewDir}/${jalviewjsSiteDir}"
3591 into jalviewjs_site_dir // this is inside the tar file
3593 inputs.dir("${jalviewDir}/${jalviewjsSiteDir}")
3597 task jalviewjsServer {
3599 def filename = "jalviewjsTest.html"
3600 description "Starts a webserver on localhost to test the website. See ${filename} to access local site on most recently used port."
3601 def htmlFile = "${jalviewDirAbsolutePath}/${filename}"
3606 def f = Class.forName("org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory")
3607 factory = f.newInstance()
3608 } catch (ClassNotFoundException e) {
3609 throw new GradleException("Unable to create SimpleHttpFileServerFactory")
3611 def port = Integer.valueOf(jalviewjs_server_port)
3616 while(port < start+1000 && !running) {
3618 def doc_root = new File("${jalviewDirAbsolutePath}/${jalviewjsSiteDir}")
3619 jalviewjsServer = factory.start(doc_root, port)
3621 url = jalviewjsServer.getResourceUrl(jalviewjs_server_resource)
3622 println("SERVER STARTED with document root ${doc_root}.")
3623 println("Go to "+url+" . Run gradle --stop to stop (kills all gradle daemons).")
3624 println("For debug: "+url+"?j2sdebug")
3625 println("For verbose: "+url+"?j2sverbose")
3626 } catch (Exception e) {
3631 <p><a href="${url}">JalviewJS Test. <${url}></a></p>
3632 <p><a href="${url}?j2sdebug">JalviewJS Test with debug. <${url}?j2sdebug></a></p>
3633 <p><a href="${url}?j2sverbose">JalviewJS Test with verbose. <${url}?j2sdebug></a></p>
3635 jalviewjsCoreClasslists.each { cl ->
3636 def urlcore = jalviewjsServer.getResourceUrl(file(cl.outputfile).getName())
3638 <p><a href="${urlcore}">${jalviewjsJalviewTemplateName} [core ${cl.name}]. <${urlcore}></a></p>
3640 println("For core ${cl.name}: "+urlcore)
3643 file(htmlFile).text = htmlText
3646 outputs.file(htmlFile)
3647 outputs.upToDateWhen({false})
3651 task cleanJalviewjsAll {
3653 description "Delete all configuration and build artifacts to do with JalviewJS build"
3654 dependsOn cleanJalviewjsSite
3655 dependsOn jalviewjsEclipsePaths
3658 delete "${jalviewDir}/${jalviewjsBuildDir}"
3659 delete "${jalviewDir}/${eclipse_bin_dir}"
3660 if (eclipseWorkspace != null && file(eclipseWorkspace.getAbsolutePath()+"/.metadata").exists()) {
3661 delete file(eclipseWorkspace.getAbsolutePath()+"/.metadata")
3663 delete jalviewjsJ2sAltSettingsFileName
3666 outputs.upToDateWhen( { false } )
3670 task jalviewjsIDE_checkJ2sPlugin {
3671 group "00 JalviewJS in Eclipse"
3672 description "Compare the swingjs/net.sf.j2s.core(-j11)?.jar file with the Eclipse IDE's plugin version (found in the 'dropins' dir)"
3675 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3676 def j2sPluginFile = file(j2sPlugin)
3677 def eclipseHome = System.properties["eclipse.home.location"]
3678 if (eclipseHome == null || ! IN_ECLIPSE) {
3679 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. Skipping J2S Plugin Check.")
3681 def eclipseJ2sPluginDirs = [ "${eclipseHome}/dropins" ]
3682 def altPluginsDir = System.properties["org.eclipse.equinox.p2.reconciler.dropins.directory"]
3683 if (altPluginsDir != null && file(altPluginsDir).exists()) {
3684 eclipseJ2sPluginDirs += altPluginsDir
3686 def foundPlugin = false
3687 def j2sPluginFileName = j2sPluginFile.getName()
3688 def eclipseJ2sPlugin
3689 def eclipseJ2sPluginFile
3690 eclipseJ2sPluginDirs.any { dir ->
3691 eclipseJ2sPlugin = "${dir}/${j2sPluginFileName}"
3692 eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3693 if (eclipseJ2sPluginFile.exists()) {
3699 def msg = "Eclipse J2S Plugin is not installed (could not find '${j2sPluginFileName}' in\n"+eclipseJ2sPluginDirs.join("\n")+"\n)\nTry running task jalviewjsIDE_copyJ2sPlugin"
3700 System.err.println(msg)
3701 throw new StopExecutionException(msg)
3704 def digest = MessageDigest.getInstance("MD5")
3706 digest.update(j2sPluginFile.text.bytes)
3707 def j2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3709 digest.update(eclipseJ2sPluginFile.text.bytes)
3710 def eclipseJ2sPluginMd5 = new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
3712 if (j2sPluginMd5 != eclipseJ2sPluginMd5) {
3713 def msg = "WARNING! Eclipse J2S Plugin '${eclipseJ2sPlugin}' is different to this commit's version '${j2sPlugin}'"
3714 System.err.println(msg)
3715 throw new StopExecutionException(msg)
3717 def msg = "Eclipse J2S Plugin '${eclipseJ2sPlugin}' is the same as '${j2sPlugin}' (this is good)"
3723 task jalviewjsIDE_copyJ2sPlugin {
3724 group "00 JalviewJS in Eclipse"
3725 description "Copy the swingjs/net.sf.j2s.core(-j11)?.jar file into the Eclipse IDE's 'dropins' dir"
3728 def j2sPlugin = string("${jalviewDir}/${jalviewjsJ2sPlugin}")
3729 def j2sPluginFile = file(j2sPlugin)
3730 def eclipseHome = System.properties["eclipse.home.location"]
3731 if (eclipseHome == null || ! IN_ECLIPSE) {
3732 throw new StopExecutionException("Cannot find running Eclipse home from System.properties['eclipse.home.location']. NOT copying J2S Plugin.")
3734 def eclipseJ2sPlugin = "${eclipseHome}/dropins/${j2sPluginFile.getName()}"
3735 def eclipseJ2sPluginFile = file(eclipseJ2sPlugin)
3736 def msg = "WARNING! Copying this commit's j2s plugin '${j2sPlugin}' to Eclipse J2S Plugin '${eclipseJ2sPlugin}'\n* May require an Eclipse restart"
3737 System.err.println(msg)
3740 eclipseJ2sPluginFile.getParentFile().mkdirs()
3741 into eclipseJ2sPluginFile.getParent()
3747 task jalviewjsIDE_j2sFile {
3748 group "00 JalviewJS in Eclipse"
3749 description "Creates the .j2s file"
3750 dependsOn jalviewjsCreateJ2sSettings
3754 task jalviewjsIDE_SyncCore {
3755 group "00 JalviewJS in Eclipse"
3756 description "Build the core js lib closures listed in the classlists dir and publish core html from template"
3757 dependsOn jalviewjsSyncCore
3761 task jalviewjsIDE_SyncSiteAll {
3762 dependsOn jalviewjsSyncAllLibs
3763 dependsOn jalviewjsSyncResources
3764 dependsOn jalviewjsSyncSiteResources
3765 dependsOn jalviewjsSyncBuildProperties
3769 cleanJalviewjsTransferSite.mustRunAfter jalviewjsIDE_SyncSiteAll
3772 task jalviewjsIDE_PrepareSite {
3773 group "00 JalviewJS in Eclipse"
3774 description "Sync libs and resources to site dir, but not closure cores"
3776 dependsOn jalviewjsIDE_SyncSiteAll
3777 //dependsOn cleanJalviewjsTransferSite // not sure why this clean is here -- will slow down a re-run of this task
3781 task jalviewjsIDE_AssembleSite {
3782 group "00 JalviewJS in Eclipse"
3783 description "Assembles unzipped supporting zipfiles, resources, site resources and closure cores into the Eclipse transpiled site"
3784 dependsOn jalviewjsPrepareSite
3788 task jalviewjsIDE_SiteClean {
3789 group "00 JalviewJS in Eclipse"
3790 description "Deletes the Eclipse transpiled site"
3791 dependsOn cleanJalviewjsSite
3795 task jalviewjsIDE_Server {
3796 group "00 JalviewJS in Eclipse"
3797 description "Starts a webserver on localhost to test the website"
3798 dependsOn jalviewjsServer
3802 // buildship runs this at import or gradle refresh
3803 task eclipseSynchronizationTask {
3804 //dependsOn eclipseSetup
3805 dependsOn createBuildProperties
3807 dependsOn jalviewjsIDE_j2sFile
3808 dependsOn jalviewjsIDE_checkJ2sPlugin
3809 dependsOn jalviewjsIDE_PrepareSite
3814 // buildship runs this at build time or project refresh
3815 task eclipseAutoBuildTask {
3816 //dependsOn jalviewjsIDE_checkJ2sPlugin
3817 //dependsOn jalviewjsIDE_PrepareSite
3823 description "Build the site"
3824 dependsOn jalviewjsBuildSite